diff options
author | Meik Sievertsen <acydburn@phpbb.com> | 2008-12-24 14:08:15 +0000 |
---|---|---|
committer | Meik Sievertsen <acydburn@phpbb.com> | 2008-12-24 14:08:15 +0000 |
commit | 68aa6bd29a0ea8c3e5b981677ace1ac188469bb8 (patch) | |
tree | bad33f1f9cd6d3efde039b2d11d250ad2dc9a960 /phpBB/modules | |
parent | 799ee3caae5de9f044ffad3e4d34010365a0005d (diff) | |
download | forums-68aa6bd29a0ea8c3e5b981677ace1ac188469bb8.tar forums-68aa6bd29a0ea8c3e5b981677ace1ac188469bb8.tar.gz forums-68aa6bd29a0ea8c3e5b981677ace1ac188469bb8.tar.bz2 forums-68aa6bd29a0ea8c3e5b981677ace1ac188469bb8.tar.xz forums-68aa6bd29a0ea8c3e5b981677ace1ac188469bb8.zip |
put acp, mcp and ucp into modules/ directory
git-svn-id: file:///svn/phpbb/trunk@9223 89ea8834-ac86-4346-8a33-228a782c2dd0
Diffstat (limited to 'phpBB/modules')
102 files changed, 40669 insertions, 0 deletions
diff --git a/phpBB/modules/acp/acp_attachments.php b/phpBB/modules/acp/acp_attachments.php new file mode 100644 index 0000000000..c4642f9dad --- /dev/null +++ b/phpBB/modules/acp/acp_attachments.php @@ -0,0 +1,1453 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_attachments +{ + var $u_action; + var $new_config; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang(array('posting', 'viewtopic', 'acp/attachments')); + + $error = $notify = array(); + $submit = request::is_set_post('submit'); + $action = request_var('action', ''); + + $form_key = 'acp_attach'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($mode) + { + case 'attach': + $l_title = 'ACP_ATTACHMENT_SETTINGS'; + break; + + case 'extensions': + $l_title = 'ACP_MANAGE_EXTENSIONS'; + break; + + case 'ext_groups': + $l_title = 'ACP_EXTENSION_GROUPS'; + break; + + case 'orphan': + $l_title = 'ACP_ORPHAN_ATTACHMENTS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $this->tpl_name = 'acp_attachments'; + $this->page_title = $l_title; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$l_title], + 'L_TITLE_EXPLAIN' => $user->lang[$l_title . '_EXPLAIN'], + 'U_ACTION' => $this->u_action) + ); + + switch ($mode) + { + case 'attach': + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + + $sql = 'SELECT group_name, cat_id + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE cat_id > 0 + ORDER BY cat_id'; + $result = $db->sql_query($sql); + + $s_assigned_groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_assigned_groups[$row['cat_id']][] = $row['group_name']; + } + $db->sql_freeresult($result); + + $l_legend_cat_images = $user->lang['SETTINGS_CAT_IMAGES'] . ' [' . $user->lang['ASSIGNED_GROUP'] . ': ' . ((!empty($s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE])) ? implode(', ', $s_assigned_groups[ATTACHMENT_CATEGORY_IMAGE]) : $user->lang['NO_EXT_GROUP']) . ']'; + + $display_vars = array( + 'title' => 'ACP_ATTACHMENT_SETTINGS', + 'vars' => array( + 'img_max_width' => false, 'img_max_height' => false, 'img_link_width' => false, 'img_link_height' => false, + + 'legend1' => 'ACP_ATTACHMENT_SETTINGS', + 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'upload_path' => array('lang' => 'UPLOAD_DIR', 'validate' => 'wpath', 'type' => 'text:25:100', 'explain' => true), + 'display_order' => array('lang' => 'DISPLAY_ORDER', 'validate' => 'bool', 'type' => 'custom', 'method' => 'display_order', 'explain' => true), + 'attachment_quota' => array('lang' => 'ATTACH_QUOTA', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_filesize' => array('lang' => 'ATTACH_MAX_FILESIZE', 'validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_filesize_pm' => array('lang' => 'ATTACH_MAX_PM_FILESIZE','validate' => 'string', 'type' => 'custom', 'method' => 'max_filesize', 'explain' => true), + 'max_attachments' => array('lang' => 'MAX_ATTACHMENTS', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), + 'max_attachments_pm' => array('lang' => 'MAX_ATTACHMENTS_PM', 'validate' => 'int', 'type' => 'text:3:3', 'explain' => false), + 'secure_downloads' => array('lang' => 'SECURE_DOWNLOADS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'secure_allow_deny' => array('lang' => 'SECURE_ALLOW_DENY', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_allow_deny', 'explain' => true), + 'secure_allow_empty_referer' => array('lang' => 'SECURE_EMPTY_REFERRER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'check_attachment_content' => array('lang' => 'CHECK_CONTENT', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + + 'legend2' => $l_legend_cat_images, + 'img_display_inlined' => array('lang' => 'DISPLAY_INLINED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'img_create_thumbnail' => array('lang' => 'CREATE_THUMBNAIL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'img_max_thumb_width' => array('lang' => 'MAX_THUMB_WIDTH', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' px'), + 'img_min_thumb_filesize' => array('lang' => 'MIN_THUMB_FILESIZE', 'validate' => 'int', 'type' => 'text:7:15', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), + 'img_imagick' => array('lang' => 'IMAGICK_PATH', 'validate' => 'string', 'type' => 'text:20:200', 'explain' => true, 'append' => ' <span>[ <a href="' . $this->u_action . '&action=imgmagick">' . $user->lang['SEARCH_IMAGICK'] . '</a> ]</span>'), + 'img_max' => array('lang' => 'MAX_IMAGE_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), + 'img_link' => array('lang' => 'IMAGE_LINK_SIZE', 'validate' => 'int', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' px'), + ) + ); + + $this->new_config = $config; + $cfg_array = (request::is_set('config')) ? request_var('config', array('' => '')) : $this->new_config; + $error = array(); + + // We validate the complete config if whished + validate_config_vars($display_vars['vars'], $cfg_array, $error); + + // Do not write values if there is an error + if (sizeof($error)) + { + $submit = false; + } + + // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to... + foreach ($display_vars['vars'] as $config_name => $null) + { + if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) + { + continue; + } + + $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; + + if (in_array($config_name, array('attachment_quota', 'max_filesize', 'max_filesize_pm'))) + { + $size_var = request_var($config_name, ''); + $this->new_config[$config_name] = $config_value = ($size_var == 'kb') ? round($config_value * 1024) : (($size_var == 'mb') ? round($config_value * 1048576) : $config_value); + } + + if ($submit) + { + set_config($config_name, $config_value); + } + } + + $this->perform_site_list(); + + if ($submit) + { + add_log('admin', 'LOG_CONFIG_ATTACH'); + + // Check Settings + $this->test_upload($error, $this->new_config['upload_path'], false); + + if (!sizeof($error)) + { + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + } + + $template->assign_var('S_ATTACHMENT_SETTINGS', true); + + if ($action == 'imgmagick') + { + $this->new_config['img_imagick'] = $this->search_imagemagick(); + } + + // We strip eventually manual added convert program, we only want the patch + if ($this->new_config['img_imagick']) + { + // Change path separator + $this->new_config['img_imagick'] = str_replace('\\', '/', $this->new_config['img_imagick']); + $this->new_config['img_imagick'] = str_replace(array('convert', '.exe'), array('', ''), $this->new_config['img_imagick']); + + // Check for trailing slash + if (substr($this->new_config['img_imagick'], -1) !== '/') + { + $this->new_config['img_imagick'] .= '/'; + } + } + + $supported_types = get_supported_image_types(); + + // Check Thumbnail Support + if (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) + { + $this->new_config['img_create_thumbnail'] = 0; + } + + $template->assign_vars(array( + 'U_SEARCH_IMAGICK' => $this->u_action . '&action=imgmagick', + 'S_THUMBNAIL_SUPPORT' => (!$this->new_config['img_imagick'] && (!isset($supported_types['format']) || !sizeof($supported_types['format']))) ? false : true) + ); + + // Secure Download Options - Same procedure as with banning + $allow_deny = ($this->new_config['secure_allow_deny']) ? 'ALLOWED' : 'DISALLOWED'; + + $sql = 'SELECT * + FROM ' . SITELIST_TABLE; + $result = $db->sql_query($sql); + + $defined_ips = ''; + $ips = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $value = ($row['site_ip']) ? $row['site_ip'] : $row['site_hostname']; + if ($value) + { + $defined_ips .= '<option' . (($row['ip_exclude']) ? ' class="sep"' : '') . ' value="' . $row['site_id'] . '">' . $value . '</option>'; + $ips[$row['site_id']] = $value; + } + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_SECURE_DOWNLOADS' => $this->new_config['secure_downloads'], + 'S_DEFINED_IPS' => ($defined_ips != '') ? true : false, + 'S_WARNING' => (sizeof($error)) ? true : false, + + 'WARNING_MSG' => implode('<br />', $error), + 'DEFINED_IPS' => $defined_ips, + + 'L_SECURE_TITLE' => $user->lang['DEFINE_' . $allow_deny . '_IPS'], + 'L_IP_EXCLUDE' => $user->lang['EXCLUDE_FROM_' . $allow_deny . '_IP'], + 'L_REMOVE_IPS' => $user->lang['REMOVE_' . $allow_deny . '_IPS']) + ); + + // Output relevant options + foreach ($display_vars['vars'] as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => (isset($user->lang[$vars])) ? $user->lang[$vars] : $vars) + ); + + continue; + } + + $type = explode(':', $vars['type']); + + $l_explain = ''; + if ($vars['explain'] && isset($vars['lang_explain'])) + { + $l_explain = (isset($user->lang[$vars['lang_explain']])) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain']; + } + else if ($vars['explain']) + { + $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; + } + + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); + if (empty($content)) + { + continue; + } + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => $user->lang[$vars['lang']], + 'S_EXPLAIN' => $vars['explain'], + 'TITLE_EXPLAIN' => $l_explain, + 'CONTENT' => $content, + ) + ); + + unset($display_vars['vars'][$config_key]); + } + + break; + + case 'extensions': + + if ($submit || request::is_set_post('add_extension_check')) + { + if ($submit) + { + // Change Extensions ? + $extension_change_list = request_var('extension_change_list', array(0)); + $group_select_list = request_var('group_select', array(0)); + + // Generate correct Change List + $extensions = array(); + + for ($i = 0, $size = sizeof($extension_change_list); $i < $size; $i++) + { + $extensions[$extension_change_list[$i]]['group_id'] = $group_select_list[$i]; + } + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . ' + ORDER BY extension_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['group_id'] != $extensions[$row['extension_id']]['group_id']) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . ' + SET group_id = ' . (int) $extensions[$row['extension_id']]['group_id'] . ' + WHERE extension_id = ' . $row['extension_id']; + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXT_UPDATE', $row['extension']); + } + } + $db->sql_freeresult($result); + + // Delete Extension? + $extension_id_list = request_var('extension_id_list', array(0)); + + if (sizeof($extension_id_list)) + { + $sql = 'SELECT extension + FROM ' . EXTENSIONS_TABLE . ' + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); + $result = $db->sql_query($sql); + + $extension_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $extension_list .= ($extension_list == '') ? $row['extension'] : ', ' . $row['extension']; + } + $db->sql_freeresult($result); + + $sql = 'DELETE + FROM ' . EXTENSIONS_TABLE . ' + WHERE ' . $db->sql_in_set('extension_id', $extension_id_list); + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXT_DEL', $extension_list); + } + } + + // Add Extension? + $add_extension = strtolower(request_var('add_extension', '')); + $add_extension_group = request_var('add_group_select', 0); + $add = request::is_set_post('add_extension_check'); + + if ($add_extension && $add) + { + if (!sizeof($error)) + { + $sql = 'SELECT extension_id + FROM ' . EXTENSIONS_TABLE . " + WHERE extension = '" . $db->sql_escape($add_extension) . "'"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $error[] = sprintf($user->lang['EXTENSION_EXIST'], $add_extension); + } + $db->sql_freeresult($result); + + if (!sizeof($error)) + { + $sql_ary = array( + 'group_id' => $add_extension_group, + 'extension' => $add_extension + ); + + $db->sql_query('INSERT INTO ' . EXTENSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + add_log('admin', 'LOG_ATTACH_EXT_ADD', $add_extension); + } + } + } + + if (!sizeof($error)) + { + $notify[] = $user->lang['EXTENSIONS_UPDATED']; + } + + $cache->destroy('_extensions'); + } + + $template->assign_vars(array( + 'S_EXTENSIONS' => true, + 'ADD_EXTENSION' => (isset($add_extension)) ? $add_extension : '', + 'GROUP_SELECT_OPTIONS' => (request::is_set_post('add_extension_check')) ? $this->group_select('add_group_select', $add_extension_group, 'extension_group') : $this->group_select('add_group_select', false, 'extension_group')) + ); + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . ' + ORDER BY group_id, extension'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $old_group_id = $row['group_id']; + do + { + $s_spacer = false; + + $current_group_id = $row['group_id']; + if ($old_group_id != $current_group_id) + { + $s_spacer = true; + $old_group_id = $current_group_id; + } + + $template->assign_block_vars('extensions', array( + 'S_SPACER' => $s_spacer, + 'EXTENSION_ID' => $row['extension_id'], + 'EXTENSION' => $row['extension'], + 'GROUP_OPTIONS' => $this->group_select('group_select[]', $row['group_id'])) + ); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + break; + + case 'ext_groups': + + $template->assign_var('S_EXTENSION_GROUPS', true); + + if ($submit) + { + $action = request_var('action', ''); + $group_id = request_var('g', 0); + + if ($action != 'add' && $action != 'edit') + { + trigger_error('NO_MODE', E_USER_ERROR); + } + + if (!$group_id && $action == 'edit') + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($group_id) + { + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $ext_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$ext_row) + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + $ext_row = array(); + } + + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $new_group_name = ($action == 'add') ? $group_name : (($ext_row['group_name'] != $group_name) ? $group_name : ''); + + if (!$group_name) + { + $error[] = $user->lang['NO_EXT_GROUP_NAME']; + } + + // Check New Group Name + if ($new_group_name) + { + $sql = 'SELECT group_name + FROM ' . EXTENSION_GROUPS_TABLE; + $result = $db->sql_query($sql); + $ext_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $clean_group_name = utf8_clean_string($new_group_name); + + while ($row = $db->sql_fetchrow($result)) + { + if (utf8_clean_string($row['group_name']) === $clean_group_name) + { + $error[] = sprintf($user->lang['EXTENSION_GROUP_EXIST'], $new_group_name); + break; + } + } + $db->sql_freeresult($result); + } + + if (!sizeof($error)) + { + // Ok, build the update/insert array + $upload_icon = request_var('upload_icon', 'no_image'); + $size_select = request_var('size_select', 'b'); + $forum_select = request_var('forum_select', false); + $allowed_forums = request_var('allowed_forums', array(0)); + $allow_in_pm = request::is_set_post('allow_in_pm'); + $max_filesize = request_var('max_filesize', 0); + $max_filesize = ($size_select == 'kb') ? round($max_filesize * 1024) : (($size_select == 'mb') ? round($max_filesize * 1048576) : $max_filesize); + $allow_group = request::is_set_post('allow_group'); + + if ($max_filesize == $config['max_filesize']) + { + $max_filesize = 0; + } + + if (!sizeof($allowed_forums)) + { + $forum_select = false; + } + + $group_ary = array( + 'group_name' => $group_name, + 'cat_id' => request_var('special_category', ATTACHMENT_CATEGORY_NONE), + 'allow_group' => ($allow_group) ? 1 : 0, + 'upload_icon' => ($upload_icon == 'no_image') ? '' : $upload_icon, + 'max_filesize' => $max_filesize, + 'allowed_forums'=> ($forum_select) ? serialize($allowed_forums) : '', + 'allow_in_pm' => ($allow_in_pm) ? 1 : 0, + ); + + if ($action == 'add') + { + $group_ary['download_mode'] = INLINE_LINK; + } + + // @TODO: rewrite with the new param db functions + $sql = ($action == 'add') ? 'INSERT INTO ' . EXTENSION_GROUPS_TABLE . ' ' : 'UPDATE ' . EXTENSION_GROUPS_TABLE . ' SET '; + $sql .= $db->sql_build_array((($action == 'add') ? 'INSERT' : 'UPDATE'), $group_ary); + $sql .= ($action == 'edit') ? " WHERE group_id = $group_id" : ''; + + $db->sql_query($sql); + + if ($action == 'add') + { + $group_id = $db->sql_nextid(); + } + + add_log('admin', 'LOG_ATTACH_EXTGROUP_' . strtoupper($action), $group_name); + } + + $extension_list = request_var('extensions', array(0)); + + if ($action == 'edit' && sizeof($extension_list)) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = 0 + WHERE group_id = $group_id"; + $db->sql_query($sql); + } + + if (sizeof($extension_list)) + { + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = $group_id + WHERE " . $db->sql_in_set('extension_id', $extension_list); + $db->sql_query($sql); + } + + $cache->destroy('_extensions'); + + if (!sizeof($error)) + { + $notify[] = $user->lang['SUCCESS_EXTENSION_GROUP_' . strtoupper($action)]; + } + } + + $cat_lang = array( + ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], + ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], + ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], + ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], + ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], + ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], + ); + + $group_id = request_var('g', 0); + $action = request::is_set_post('add'); + + switch ($action) + { + case 'delete': + + if (confirm_box(true)) + { + $sql = 'SELECT group_name + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_name = (string) $db->sql_fetchfield('group_name'); + $db->sql_freeresult($result); + + $sql = 'DELETE + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $db->sql_query($sql); + + // Set corresponding Extensions to a pending Group + $sql = 'UPDATE ' . EXTENSIONS_TABLE . " + SET group_id = 0 + WHERE group_id = $group_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_EXTGROUP_DEL', $group_name); + + $cache->destroy('_extensions'); + + trigger_error($user->lang['EXTENSION_GROUP_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'group_id' => $group_id, + 'action' => 'delete', + ))); + } + + break; + + case 'edit': + + if (!$group_id) + { + trigger_error($user->lang['NO_EXT_GROUP_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $ext_group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $forum_ids = (!$ext_group_row['allowed_forums']) ? array() : unserialize(trim($ext_group_row['allowed_forums'])); + + // no break; + + case 'add': + + if ($action == 'add') + { + $ext_group_row = array( + 'group_name' => utf8_normalize_nfc(request_var('group_name', '', true)), + 'cat_id' => 0, + 'allow_group' => 1, + 'allow_in_pm' => 1, + 'upload_icon' => '', + 'max_filesize' => 0, + ); + + $forum_ids = array(); + } + + $extensions = array(); + + $sql = 'SELECT * + FROM ' . EXTENSIONS_TABLE . " + WHERE group_id = $group_id + OR group_id = 0 + ORDER BY extension"; + $result = $db->sql_query($sql); + $extensions = $db->sql_fetchrowset($result); + $db->sql_freeresult($result); + + if ($ext_group_row['max_filesize'] == 0) + { + $ext_group_row['max_filesize'] = (int) $config['max_filesize']; + } + + $size_format = ($ext_group_row['max_filesize'] >= 1048576) ? 'mb' : (($ext_group_row['max_filesize'] >= 1024) ? 'kb' : 'b'); + $ext_group_row['max_filesize'] = get_formatted_filesize($ext_group_row['max_filesize'], false); + + $img_path = $config['upload_icons_path']; + + $filename_list = ''; + $no_image_select = false; + + $imglist = filelist(PHPBB_ROOT_PATH . $img_path); + + if (sizeof($imglist)) + { + $imglist = array_values($imglist); + $imglist = $imglist[0]; + + foreach ($imglist as $key => $img) + { + if (!$ext_group_row['upload_icon']) + { + $no_image_select = true; + $selected = ''; + } + else + { + $selected = ($ext_group_row['upload_icon'] == $img) ? ' selected="selected"' : ''; + } + + if (strlen($img) > 255) + { + continue; + } + + $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . htmlspecialchars($img) . '</option>'; + } + } + + $i = 0; + $assigned_extensions = ''; + foreach ($extensions as $num => $row) + { + if ($row['group_id'] == $group_id && $group_id) + { + $assigned_extensions .= ($i) ? ', ' . $row['extension'] : $row['extension']; + $i++; + } + } + + $s_extension_options = ''; + foreach ($extensions as $row) + { + $s_extension_options .= '<option' . ((!$row['group_id']) ? ' class="disabled"' : '') . ' value="' . $row['extension_id'] . '"' . (($row['group_id'] == $group_id && $group_id) ? ' selected="selected"' : '') . '>' . $row['extension'] . '</option>'; + } + + $template->assign_vars(array( + 'PHPBB_ROOT_PATH' => PHPBB_ROOT_PATH, + 'IMG_PATH' => $img_path, + 'ACTION' => $action, + 'GROUP_ID' => $group_id, + 'GROUP_NAME' => $ext_group_row['group_name'], + 'ALLOW_GROUP' => $ext_group_row['allow_group'], + 'ALLOW_IN_PM' => $ext_group_row['allow_in_pm'], + 'UPLOAD_ICON_SRC' => PHPBB_ROOT_PATH . $img_path . '/' . $ext_group_row['upload_icon'], + 'EXTGROUP_FILESIZE' => $ext_group_row['max_filesize'], + 'ASSIGNED_EXTENSIONS' => $assigned_extensions, + + 'S_CATEGORY_SELECT' => $this->category_select('special_category', $group_id, 'category'), + 'S_EXT_GROUP_SIZE_OPTIONS' => size_select_options($size_format), + 'S_EXTENSION_OPTIONS' => $s_extension_options, + 'S_FILENAME_LIST' => $filename_list, + 'S_EDIT_GROUP' => true, + 'S_NO_IMAGE' => $no_image_select, + 'S_FORUM_IDS' => (sizeof($forum_ids)) ? true : false, + + 'U_EXTENSIONS' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&mode=extensions"), + 'U_BACK' => $this->u_action, + + 'L_LEGEND' => $user->lang[strtoupper($action) . '_EXTENSION_GROUP']) + ); + + $s_forum_id_options = ''; + + /** @todo use in-built function **/ + + $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id ASC'; + $result = $db->sql_query($sql, 600); + + $right = $cat_right = $padding_inc = 0; + $padding = $forum_list = $holding = ''; + $padding_store = array('0' => ''); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id'])) + { + // Non-postable forum with no subforums, don't display + continue; + } + + if (!$auth->acl_get('f_list', $row['forum_id'])) + { + // if the user does not have permissions to list this forum skip + continue; + } + + if ($row['left_id'] < $right) + { + $padding .= ' '; + $padding_store[$row['parent_id']] = $padding; + } + else if ($row['left_id'] > $right + 1) + { + $padding = empty($padding_store[$row['parent_id']]) ? '' : $padding_store[$row['parent_id']]; + } + + $right = $row['right_id']; + + $selected = (in_array($row['forum_id'], $forum_ids)) ? ' selected="selected"' : ''; + + if ($row['left_id'] > $cat_right) + { + // make sure we don't forget anything + $s_forum_id_options .= $holding; + $holding = ''; + } + + if ($row['right_id'] - $row['left_id'] > 1) + { + $cat_right = max($cat_right, $row['right_id']); + + $holding .= '<option value="' . $row['forum_id'] . '"' . (($row['forum_type'] == FORUM_POST) ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>'; + } + else + { + $s_forum_id_options .= $holding . '<option value="' . $row['forum_id'] . '"' . (($row['forum_type'] == FORUM_POST) ? ' class="sep"' : '') . $selected . '>' . $padding . $row['forum_name'] . '</option>'; + $holding = ''; + } + } + + if ($holding) + { + $s_forum_id_options .= $holding; + } + + $db->sql_freeresult($result); + unset($padding_store); + + $template->assign_vars(array( + 'S_FORUM_ID_OPTIONS' => $s_forum_id_options) + ); + + break; + } + + $sql = 'SELECT * + FROM ' . EXTENSION_GROUPS_TABLE . ' + ORDER BY allow_group DESC, allow_in_pm DESC, group_name'; + $result = $db->sql_query($sql); + + $old_allow_group = $old_allow_pm = 1; + while ($row = $db->sql_fetchrow($result)) + { + $s_add_spacer = ($old_allow_group != $row['allow_group'] || $old_allow_pm != $row['allow_in_pm']) ? true : false; + + $template->assign_block_vars('groups', array( + 'S_ADD_SPACER' => $s_add_spacer, + 'S_ALLOWED_IN_PM' => ($row['allow_in_pm']) ? true : false, + 'S_GROUP_ALLOWED' => ($row['allow_group']) ? true : false, + + 'U_EDIT' => $this->u_action . "&action=edit&g={$row['group_id']}", + 'U_DELETE' => $this->u_action . "&action=delete&g={$row['group_id']}", + + 'GROUP_NAME' => $row['group_name'], + 'CATEGORY' => $cat_lang[$row['cat_id']], + ) + ); + + $old_allow_group = $row['allow_group']; + $old_allow_pm = $row['allow_in_pm']; + } + $db->sql_freeresult($result); + + break; + + case 'orphan': + + if ($submit) + { + $delete_files = array_keys(request::variable('delete', array('' => 0), false, request::POST)); + $add_files = array_keys(request::variable('add', array('' => 0), false, request::POST)); + $post_ids = request_var('post_id', array('' => 0)); + + if (sizeof($delete_files)) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', $delete_files) . ' + AND is_orphan = 1'; + $result = $db->sql_query($sql); + + $delete_files = array(); + while ($row = $db->sql_fetchrow($result)) + { + phpbb_unlink($row['physical_filename'], 'file'); + + if ($row['thumbnail']) + { + phpbb_unlink($row['physical_filename'], 'thumbnail'); + } + + $delete_files[$row['attach_id']] = $row['real_filename']; + } + $db->sql_freeresult($result); + } + + if (sizeof($delete_files)) + { + $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', array_keys($delete_files)); + $db->sql_query($sql); + + add_log('admin', 'LOG_ATTACH_ORPHAN_DEL', implode(', ', $delete_files)); + $notify[] = sprintf($user->lang['LOG_ATTACH_ORPHAN_DEL'], implode(', ', $delete_files)); + } + + $upload_list = array(); + foreach ($add_files as $attach_id) + { + if (!isset($delete_files[$attach_id]) && !empty($post_ids[$attach_id])) + { + $upload_list[$attach_id] = $post_ids[$attach_id]; + } + } + unset($add_files); + + if (sizeof($upload_list)) + { + $template->assign_var('S_UPLOADING_FILES', true); + + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT forum_id, topic_id, post_id, poster_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $upload_list); + $result = $db->sql_query($sql); + + $post_info = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_info[$row['post_id']] = $row; + } + $db->sql_freeresult($result); + + // Select those attachments we want to change... + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', array_keys($upload_list)) . ' + AND is_orphan = 1'; + $result = $db->sql_query($sql); + + $files_added = $space_taken = 0; + while ($row = $db->sql_fetchrow($result)) + { + $post_row = $post_info[$upload_list[$row['attach_id']]]; + + $template->assign_block_vars('upload', array( + 'FILE_INFO' => sprintf($user->lang['UPLOADING_FILE_TO'], $row['real_filename'], $post_row['post_id']), + 'S_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? true : false, + 'L_DENIED' => (!$auth->acl_get('f_attach', $post_row['forum_id'])) ? sprintf($user->lang['UPLOAD_DENIED_FORUM'], $forum_names[$row['forum_id']]) : '') + ); + + if (!$auth->acl_get('f_attach', $post_row['forum_id'])) + { + continue; + } + + // Adjust attachment entry + $sql_ary = array( + 'in_message' => 0, + 'is_orphan' => 0, + 'poster_id' => $post_row['poster_id'], + 'post_msg_id' => $post_row['post_id'], + 'topic_id' => $post_row['topic_id'], + ); + + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE attach_id = ' . $row['attach_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_attachment = 1 + WHERE post_id = ' . $post_row['post_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_attachment = 1 + WHERE topic_id = ' . $post_row['topic_id']; + $db->sql_query($sql); + + $space_taken += $row['filesize']; + $files_added++; + + add_log('admin', 'LOG_ATTACH_FILEUPLOAD', $post_row['post_id'], $row['real_filename']); + } + $db->sql_freeresult($result); + + if ($files_added) + { + set_config('upload_dir_size', $config['upload_dir_size'] + $space_taken, true); + set_config('num_files', $config['num_files'] + $files_added, true); + } + } + } + + $template->assign_vars(array( + 'S_ORPHAN' => true) + ); + + // Just get the files with is_orphan set and older than 3 hours + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 1 + AND filetime < ' . (time() - 3*60*60) . ' + ORDER BY filetime DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('orphan', array( + 'FILESIZE' => get_formatted_filesize($row['filesize']), + 'FILETIME' => $user->format_date($row['filetime']), + 'REAL_FILENAME' => basename($row['real_filename']), + 'PHYSICAL_FILENAME' => basename($row['physical_filename']), + 'ATTACH_ID' => $row['attach_id'], + 'POST_IDS' => (!empty($post_ids[$row['attach_id']])) ? $post_ids[$row['attach_id']] : '', + 'U_FILE' => append_sid('download/file', 'mode=view&id=' . $row['attach_id'])) + ); + } + $db->sql_freeresult($result); + + break; + } + + if (sizeof($error)) + { + $template->assign_vars(array( + 'S_WARNING' => true, + 'WARNING_MSG' => implode('<br />', $error)) + ); + } + + if (sizeof($notify)) + { + $template->assign_vars(array( + 'S_NOTIFY' => true, + 'NOTIFY_MSG' => implode('<br />', $notify)) + ); + } + } + + /** + * Build Select for category items + */ + function category_select($select_name, $group_id = false, $key = '') + { + global $db, $user; + + $types = array( + ATTACHMENT_CATEGORY_NONE => $user->lang['NO_FILE_CAT'], + ATTACHMENT_CATEGORY_IMAGE => $user->lang['CAT_IMAGES'], + ATTACHMENT_CATEGORY_WM => $user->lang['CAT_WM_FILES'], + ATTACHMENT_CATEGORY_RM => $user->lang['CAT_RM_FILES'], + ATTACHMENT_CATEGORY_FLASH => $user->lang['CAT_FLASH_FILES'], + ATTACHMENT_CATEGORY_QUICKTIME => $user->lang['CAT_QUICKTIME_FILES'], + ); + + if ($group_id) + { + $sql = 'SELECT cat_id + FROM ' . EXTENSION_GROUPS_TABLE . ' + WHERE group_id = ' . (int) $group_id; + $result = $db->sql_query($sql); + + $cat_type = (!($row = $db->sql_fetchrow($result))) ? ATTACHMENT_CATEGORY_NONE : $row['cat_id']; + + $db->sql_freeresult($result); + } + else + { + $cat_type = ATTACHMENT_CATEGORY_NONE; + } + + $group_select = '<select name="' . $select_name . '"' . (($key) ? ' id="' . $key . '"' : '') . '>'; + + foreach ($types as $type => $mode) + { + $selected = ($type == $cat_type) ? ' selected="selected"' : ''; + $group_select .= '<option value="' . $type . '"' . $selected . '>' . $mode . '</option>'; + } + + $group_select .= '</select>'; + + return $group_select; + } + + /** + * Extension group select + */ + function group_select($select_name, $default_group = false, $key = '') + { + global $db, $user; + + $group_select = '<select name="' . $select_name . '"' . (($key) ? ' id="' . $key . '"' : '') . '>'; + + $sql = 'SELECT group_id, group_name + FROM ' . EXTENSION_GROUPS_TABLE . ' + ORDER BY group_name'; + $result = $db->sql_query($sql); + + $group_name = array(); + while ($row = $db->sql_fetchrow($result)) + { + $group_name[] = $row; + } + $db->sql_freeresult($result); + + $row['group_id'] = 0; + $row['group_name'] = $user->lang['NOT_ASSIGNED']; + $group_name[] = $row; + + for ($i = 0; $i < sizeof($group_name); $i++) + { + if ($default_group === false) + { + $selected = ($i == 0) ? ' selected="selected"' : ''; + } + else + { + $selected = ($group_name[$i]['group_id'] == $default_group) ? ' selected="selected"' : ''; + } + + $group_select .= '<option value="' . $group_name[$i]['group_id'] . '"' . $selected . '>' . $group_name[$i]['group_name'] . '</option>'; + } + + $group_select .= '</select>'; + + return $group_select; + } + + /** + * Search Imagick + */ + function search_imagemagick() + { + $imagick = ''; + + $exe = ((defined('PHP_OS')) && (preg_match('#^win#i', PHP_OS))) ? '.exe' : ''; + + $magic_home = getenv('MAGICK_HOME'); + + if (empty($magic_home)) + { + $locations = array('C:/WINDOWS/', 'C:/WINNT/', 'C:/WINDOWS/SYSTEM/', 'C:/WINNT/SYSTEM/', 'C:/WINDOWS/SYSTEM32/', 'C:/WINNT/SYSTEM32/', '/usr/bin/', '/usr/sbin/', '/usr/local/bin/', '/usr/local/sbin/', '/opt/', '/usr/imagemagick/', '/usr/bin/imagemagick/'); + $path_locations = str_replace('\\', '/', (explode(($exe) ? ';' : ':', getenv('PATH')))); + + $locations = array_merge($path_locations, $locations); + + foreach ($locations as $location) + { + // The path might not end properly, fudge it + if (substr($location, -1) !== '/') + { + $location .= '/'; + } + + if (@file_exists($location) && @is_readable($location . 'mogrify' . $exe) && @filesize($location . 'mogrify' . $exe) > 3000) + { + $imagick = str_replace('\\', '/', $location); + continue; + } + } + } + else + { + $imagick = str_replace('\\', '/', $magic_home); + } + + return $imagick; + } + + /** + * Test Settings + */ + function test_upload(&$error, $upload_dir, $create_directory = false) + { + global $user; + + // Does the target directory exist, is it a directory and writable. + if ($create_directory) + { + if (!file_exists(PHPBB_ROOT_PATH . $upload_dir)) + { + @mkdir(PHPBB_ROOT_PATH . $upload_dir, 0777); + phpbb_chmod(PHPBB_ROOT_PATH . $upload_dir, CHMOD_READ | CHMOD_WRITE); + } + } + + if (!file_exists(PHPBB_ROOT_PATH . $upload_dir)) + { + $error[] = sprintf($user->lang['NO_UPLOAD_DIR'], $upload_dir); + return; + } + + if (!is_dir(PHPBB_ROOT_PATH . $upload_dir)) + { + $error[] = sprintf($user->lang['UPLOAD_NOT_DIR'], $upload_dir); + return; + } + + if (!is_writable(PHPBB_ROOT_PATH . $upload_dir)) + { + $error[] = sprintf($user->lang['NO_WRITE_UPLOAD'], $upload_dir); + return; + } + } + + /** + * Perform operations on sites for external linking + */ + function perform_site_list() + { + global $db, $user; + + if (request::is_set('securesubmit')) + { + // Grab the list of entries + $ips = request_var('ips', ''); + $ip_list = array_unique(explode("\n", $ips)); + $ip_list_log = implode(', ', $ip_list); + + $ip_exclude = (int) request::variable('ipexclude', false, false, request::POST); + + $iplist = array(); + $hostlist = array(); + + foreach ($ip_list as $item) + { + if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($item), $ip_range_explode)) + { + // Don't ask about all this, just don't ask ... ! + $ip_1_counter = $ip_range_explode[1]; + $ip_1_end = $ip_range_explode[5]; + + while ($ip_1_counter <= $ip_1_end) + { + $ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0; + $ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6]; + + if ($ip_2_counter == 0 && $ip_2_end == 254) + { + $ip_2_counter = 256; + $ip_2_fragment = 256; + + $iplist[] = "'$ip_1_counter.*'"; + } + + while ($ip_2_counter <= $ip_2_end) + { + $ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0; + $ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7]; + + if ($ip_3_counter == 0 && $ip_3_end == 254) + { + $ip_3_counter = 256; + $ip_3_fragment = 256; + + $iplist[] = "'$ip_1_counter.$ip_2_counter.*'"; + } + + while ($ip_3_counter <= $ip_3_end) + { + $ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0; + $ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8]; + + if ($ip_4_counter == 0 && $ip_4_end == 254) + { + $ip_4_counter = 256; + $ip_4_fragment = 256; + + $iplist[] = "'$ip_1_counter.$ip_2_counter.$ip_3_counter.*'"; + } + + while ($ip_4_counter <= $ip_4_end) + { + $iplist[] = "'$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter'"; + $ip_4_counter++; + } + $ip_3_counter++; + } + $ip_2_counter++; + } + $ip_1_counter++; + } + } + else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($item))) + { + $iplist[] = "'" . trim($item) . "'"; + } + else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($item))) + { + $hostlist[] = "'" . trim($item) . "'"; + } + else if (preg_match("#^([a-z0-9\-\*\._/]+?)$#is", trim($item))) + { + $hostlist[] = "'" . trim($item) . "'"; + } + } + + $sql = 'SELECT site_ip, site_hostname + FROM ' . SITELIST_TABLE . " + WHERE ip_exclude = $ip_exclude"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $iplist_tmp = array(); + $hostlist_tmp = array(); + do + { + if ($row['site_ip']) + { + if (strlen($row['site_ip']) > 40) + { + continue; + } + + $iplist_tmp[] = "'" . $row['site_ip'] . "'"; + } + else if ($row['site_hostname']) + { + if (strlen($row['site_hostname']) > 255) + { + continue; + } + + $hostlist_tmp[] = "'" . $row['site_hostname'] . "'"; + } + // break; + } + while ($row = $db->sql_fetchrow($result)); + + $iplist = array_unique(array_diff($iplist, $iplist_tmp)); + $hostlist = array_unique(array_diff($hostlist, $hostlist_tmp)); + unset($iplist_tmp); + unset($hostlist_tmp); + } + $db->sql_freeresult($result); + + if (sizeof($iplist)) + { + foreach ($iplist as $ip_entry) + { + $sql = 'INSERT INTO ' . SITELIST_TABLE . " (site_ip, ip_exclude) + VALUES ($ip_entry, $ip_exclude)"; + $db->sql_query($sql); + } + } + + if (sizeof($hostlist)) + { + foreach ($hostlist as $host_entry) + { + $sql = 'INSERT INTO ' . SITELIST_TABLE . " (site_hostname, ip_exclude) + VALUES ($host_entry, $ip_exclude)"; + $db->sql_query($sql); + } + } + + if (!empty($ip_list_log)) + { + // Update log + $log_entry = ($ip_exclude) ? 'LOG_DOWNLOAD_EXCLUDE_IP' : 'LOG_DOWNLOAD_IP'; + add_log('admin', $log_entry, $ip_list_log); + } + + trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); + } + else if (request::is_set_post('unsecuresubmit')) + { + $unip_sql = request_var('unip', array(0)); + + if (sizeof($unip_sql)) + { + $l_unip_list = ''; + + // Grab details of ips for logging information later + $sql = 'SELECT site_ip, site_hostname + FROM ' . SITELIST_TABLE . ' + WHERE ' . $db->sql_in_set('site_id', $unip_sql); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $l_unip_list .= (($l_unip_list != '') ? ', ' : '') . (($row['site_ip']) ? $row['site_ip'] : $row['site_hostname']); + } + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . SITELIST_TABLE . ' + WHERE ' . $db->sql_in_set('site_id', $unip_sql); + $db->sql_query($sql); + + add_log('admin', 'LOG_DOWNLOAD_REMOVE_IP', $l_unip_list); + } + + trigger_error($user->lang['SECURE_DOWNLOAD_UPDATE_SUCCESS'] . adm_back_link($this->u_action)); + } + } + + /** + * Write display_order config field + */ + function display_order($value, $key = '') + { + $radio_ary = array(0 => 'DESCENDING', 1 => 'ASCENDING'); + + return h_radio('config[display_order]', $radio_ary, $value, $key); + } + + /** + * Adjust all three max_filesize config vars for display + */ + function max_filesize($value, $key = '') + { + // Determine size var and adjust the value accordingly + $size_var = ($value >= 1048576) ? 'mb' : (($value >= 1024) ? 'kb' : 'b'); + $value = get_formatted_filesize($value, false); + + return '<input type="text" id="' . $key . '" size="8" maxlength="15" name="config[' . $key . ']" value="' . $value . '" /> <select name="' . $key . '">' . size_select_options($size_var) . '</select>'; + } + + /** + * Write secure_allow_deny config field + */ + function select_allow_deny($value, $key = '') + { + $radio_ary = array(1 => 'ORDER_ALLOW_DENY', 0 => 'ORDER_DENY_ALLOW'); + + return h_radio('config[' . $key . ']', $radio_ary, $value, $key); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_ban.php b/phpBB/modules/acp/acp_ban.php new file mode 100644 index 0000000000..8456c957a2 --- /dev/null +++ b/phpBB/modules/acp/acp_ban.php @@ -0,0 +1,234 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_ban +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $bansubmit = request::is_set_post('bansubmit'); + $unbansubmit = request::is_set_post('unbansubmit'); + $current_time = time(); + + $user->add_lang(array('acp/ban', 'acp/users')); + $this->tpl_name = 'acp_ban'; + $form_key = 'acp_ban'; + add_form_key($form_key); + + if (($bansubmit || $unbansubmit) && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Ban submitted? + if ($bansubmit) + { + // Grab the list of entries + $ban = utf8_normalize_nfc(request_var('ban', '', true)); + $ban_len = request_var('banlength', 0); + $ban_len_other = request_var('banlengthother', ''); + $ban_exclude = request_var('banexclude', 0); + $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); + $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + + if ($ban) + { + user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action)); + } + } + else if ($unbansubmit) + { + $ban = request_var('unban', array('')); + + if ($ban) + { + user_unban($mode, $ban); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action)); + } + } + + // Define language vars + $this->page_title = $user->lang[strtoupper($mode) . '_BAN']; + + $l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN']; + $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN']; + $l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN']; + $l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN']; + $l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED']; + + switch ($mode) + { + case 'user': + $l_ban_cell = $user->lang['USERNAME']; + break; + + case 'ip': + $l_ban_cell = $user->lang['IP_HOSTNAME']; + break; + + case 'email': + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + break; + } + + self::display_ban_options($mode); + + $template->assign_vars(array( + 'L_TITLE' => $this->page_title, + 'L_EXPLAIN' => $l_ban_explain, + 'L_UNBAN_TITLE' => $l_unban_title, + 'L_UNBAN_EXPLAIN' => $l_unban_explain, + 'L_BAN_CELL' => $l_ban_cell, + 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain, + 'L_NO_BAN_CELL' => $l_no_ban_cell, + + 'S_USERNAME_BAN' => ($mode == 'user') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=acp_ban&field=ban'), + )); + } + + /** + * Display ban options + */ + static function display_ban_options($mode) + { + global $user, $db, $template; + + // Ban length options + $ban_end_text = array(0 => $user->lang['PERMANENT'], 30 => $user->lang['30_MINS'], 60 => $user->lang['1_HOUR'], 360 => $user->lang['6_HOURS'], 1440 => $user->lang['1_DAY'], 10080 => $user->lang['7_DAYS'], 20160 => $user->lang['2_WEEKS'], 40320 => $user->lang['1_MONTH'], -1 => $user->lang['UNTIL'] . ' -> '); + + $ban_end_options = ''; + foreach ($ban_end_text as $length => $text) + { + $ban_end_options .= '<option value="' . $length . '">' . $text . '</option>'; + } + + switch ($mode) + { + case 'user': + + $field = 'username'; + $l_ban_cell = $user->lang['USERNAME']; + + $sql = 'SELECT b.*, u.user_id, u.username, u.username_clean + FROM ' . BANLIST_TABLE . ' b, ' . USERS_TABLE . ' u + WHERE (b.ban_end >= ' . time() . ' + OR b.ban_end = 0) + AND u.user_id = b.ban_userid + ORDER BY u.username_clean ASC'; + break; + + case 'ip': + + $field = 'ban_ip'; + $l_ban_cell = $user->lang['IP_HOSTNAME']; + + $sql = 'SELECT * + FROM ' . BANLIST_TABLE . ' + WHERE (ban_end >= ' . time() . " + OR ban_end = 0) + AND ban_ip <> ''"; + break; + + case 'email': + + $field = 'ban_email'; + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + + $sql = 'SELECT * + FROM ' . BANLIST_TABLE . ' + WHERE (ban_end >= ' . time() . " + OR ban_end = 0) + AND ban_email <> ''"; + break; + } + $result = $db->sql_query($sql); + + $banned_options = ''; + $ban_length = $ban_reasons = $ban_give_reasons = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $banned_options .= '<option' . (($row['ban_exclude']) ? ' class="sep"' : '') . ' value="' . $row['ban_id'] . '">' . $row[$field] . '</option>'; + + $time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0; + $ban_length[$row['ban_id']] = (isset($ban_end_text[$time_length])) ? $ban_end_text[$time_length] : $user->lang['UNTIL'] . ' -> ' . $user->format_date($row['ban_end']); + + $ban_reasons[$row['ban_id']] = $row['ban_reason']; + $ban_give_reasons[$row['ban_id']] = $row['ban_give_reason']; + } + $db->sql_freeresult($result); + + if (sizeof($ban_length)) + { + foreach ($ban_length as $ban_id => $length) + { + $template->assign_block_vars('ban_length', array( + 'BAN_ID' => (int) $ban_id, + 'LENGTH' => $length, + 'A_LENGTH' => addslashes($length), + )); + } + } + + if (sizeof($ban_reasons)) + { + foreach ($ban_reasons as $ban_id => $reason) + { + $template->assign_block_vars('ban_reason', array( + 'BAN_ID' => $ban_id, + 'REASON' => $reason, + 'A_REASON' => addslashes(htmlspecialchars_decode($reason)), + )); + } + } + + if (sizeof($ban_give_reasons)) + { + foreach ($ban_give_reasons as $ban_id => $reason) + { + $template->assign_block_vars('ban_give_reason', array( + 'BAN_ID' => $ban_id, + 'REASON' => $reason, + 'A_REASON' => addslashes(htmlspecialchars_decode($reason)), + )); + } + } + + $template->assign_vars(array( + 'S_BAN_END_OPTIONS' => $ban_end_options, + 'S_BANNED_OPTIONS' => ($banned_options) ? true : false, + 'BANNED_OPTIONS' => $banned_options) + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_bbcodes.php b/phpBB/modules/acp/acp_bbcodes.php new file mode 100644 index 0000000000..4118e5f919 --- /dev/null +++ b/phpBB/modules/acp/acp_bbcodes.php @@ -0,0 +1,442 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_bbcodes +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $bbcode_id = request_var('bbcode', 0); + + $this->tpl_name = 'acp_bbcodes'; + $this->page_title = 'ACP_BBCODES'; + $form_key = 'acp_bbcodes'; + + add_form_key($form_key); + + // Set up mode-specific vars + switch ($action) + { + case 'add': + $bbcode_match = $bbcode_tpl = $bbcode_helpline = ''; + $display_on_posting = 0; + break; + + case 'edit': + $sql = 'SELECT bbcode_match, bbcode_tpl, display_on_posting, bbcode_helpline + FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . $bbcode_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $bbcode_match = $row['bbcode_match']; + $bbcode_tpl = htmlspecialchars($row['bbcode_tpl']); + $display_on_posting = $row['display_on_posting']; + $bbcode_helpline = $row['bbcode_helpline']; + break; + + case 'modify': + $sql = 'SELECT bbcode_id, bbcode_tag + FROM ' . BBCODES_TABLE . ' + WHERE bbcode_id = ' . $bbcode_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['BBCODE_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // No break here + + case 'create': + $display_on_posting = request_var('display_on_posting', 0); + + $bbcode_match = request_var('bbcode_match', ''); + $bbcode_tpl = htmlspecialchars_decode(utf8_normalize_nfc(request_var('bbcode_tpl', '', true))); + $bbcode_helpline = utf8_normalize_nfc(request_var('bbcode_helpline', '', true)); + break; + } + + // Do major work + switch ($action) + { + case 'edit': + case 'add': + + $template->assign_vars(array( + 'S_EDIT_BBCODE' => true, + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify') . (($bbcode_id) ? "&bbcode=$bbcode_id" : ''), + + 'L_BBCODE_USAGE_EXPLAIN'=> sprintf($user->lang['BBCODE_USAGE_EXPLAIN'], '<a href="#down">', '</a>'), + 'BBCODE_MATCH' => $bbcode_match, + 'BBCODE_TPL' => $bbcode_tpl, + 'BBCODE_HELPLINE' => $bbcode_helpline, + 'DISPLAY_ON_POSTING' => $display_on_posting) + ); + + foreach ($user->lang['tokens'] as $token => $token_explain) + { + $template->assign_block_vars('token', array( + 'TOKEN' => '{' . $token . '}', + 'EXPLAIN' => $token_explain) + ); + } + + return; + + break; + + case 'modify': + case 'create': + + $data = $this->build_regexp($bbcode_match, $bbcode_tpl); + + // Make sure the user didn't pick a "bad" name for the BBCode tag. + $hard_coded = array('code', 'quote', 'quote=', 'attachment', 'attachment=', 'b', 'i', 'url', 'url=', 'img', 'size', 'size=', 'color', 'color=', 'u', 'list', 'list=', 'email', 'email=', 'flash', 'flash='); + + if (($action == 'modify' && strtolower($data['bbcode_tag']) !== strtolower($row['bbcode_tag'])) || ($action == 'create')) + { + $sql = 'SELECT 1 as test + FROM ' . BBCODES_TABLE . " + WHERE LOWER(bbcode_tag) = '" . $db->sql_escape(strtolower($data['bbcode_tag'])) . "'"; + $result = $db->sql_query($sql); + $info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Grab the end, interrogate the last closing tag + if ($info['test'] === '1' || in_array(strtolower($data['bbcode_tag']), $hard_coded) || (preg_match('#\[/([^[]*)]$#', $bbcode_match, $regs) && in_array(strtolower($regs[1]), $hard_coded))) + { + trigger_error($user->lang['BBCODE_INVALID_TAG_NAME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + if (substr($data['bbcode_tag'], -1) === '=') + { + $test = substr($data['bbcode_tag'], 0, -1); + } + else + { + $test = $data['bbcode_tag']; + } + + if (!preg_match('%\\[' . $test . '[^]]*].*?\\[/' . $test . ']%s', $bbcode_match)) + { + trigger_error($user->lang['BBCODE_OPEN_ENDED_TAG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strlen($data['bbcode_tag']) > 16) + { + trigger_error($user->lang['BBCODE_TAG_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strlen($bbcode_match) > 4000) + { + trigger_error($user->lang['BBCODE_TAG_DEF_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + + if (strlen($bbcode_helpline) > 255) + { + trigger_error($user->lang['BBCODE_HELPLINE_TOO_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'bbcode_tag' => $data['bbcode_tag'], + 'bbcode_match' => $bbcode_match, + 'bbcode_tpl' => $bbcode_tpl, + 'display_on_posting' => $display_on_posting, + 'bbcode_helpline' => $bbcode_helpline, + 'first_pass_match' => $data['first_pass_match'], + 'first_pass_replace' => $data['first_pass_replace'], + 'second_pass_match' => $data['second_pass_match'], + 'second_pass_replace' => $data['second_pass_replace'] + ); + + if ($action == 'create') + { + $sql = 'SELECT MAX(bbcode_id) as max_bbcode_id + FROM ' . BBCODES_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $bbcode_id = $row['max_bbcode_id'] + 1; + + // Make sure it is greater than the core bbcode ids... + if ($bbcode_id <= NUM_CORE_BBCODES) + { + $bbcode_id = NUM_CORE_BBCODES + 1; + } + } + else + { + $bbcode_id = NUM_CORE_BBCODES + 1; + } + + if ($bbcode_id > 1511) + { + trigger_error($user->lang['TOO_MANY_BBCODES'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary['bbcode_id'] = (int) $bbcode_id; + + $db->sql_query('INSERT INTO ' . BBCODES_TABLE . $db->sql_build_array('INSERT', $sql_ary)); + $cache->destroy('sql', BBCODES_TABLE); + + $lang = 'BBCODE_ADDED'; + $log_action = 'LOG_BBCODE_ADD'; + } + else + { + $sql = 'UPDATE ' . BBCODES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE bbcode_id = ' . $bbcode_id; + $db->sql_query($sql); + $cache->destroy('sql', BBCODES_TABLE); + + $lang = 'BBCODE_EDITED'; + $log_action = 'LOG_BBCODE_EDIT'; + } + + add_log('admin', $log_action, $data['bbcode_tag']); + + trigger_error($user->lang[$lang] . adm_back_link($this->u_action)); + + break; + + case 'delete': + + $sql = 'SELECT bbcode_tag + FROM ' . BBCODES_TABLE . " + WHERE bbcode_id = $bbcode_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + if (confirm_box(true)) + { + $db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id"); + $cache->destroy('sql', BBCODES_TABLE); + add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'bbcode' => $bbcode_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=add') + ); + + $sql = 'SELECT * + FROM ' . BBCODES_TABLE . ' + ORDER BY bbcode_tag'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('bbcodes', array( + 'BBCODE_TAG' => $row['bbcode_tag'], + 'U_EDIT' => $this->u_action . '&action=edit&bbcode=' . $row['bbcode_id'], + 'U_DELETE' => $this->u_action . '&action=delete&bbcode=' . $row['bbcode_id']) + ); + } + $db->sql_freeresult($result); + } + + /* + * Build regular expression for custom bbcode + */ + function build_regexp(&$bbcode_match, &$bbcode_tpl) + { + $bbcode_match = trim($bbcode_match); + $bbcode_tpl = trim($bbcode_tpl); + + $fp_match = preg_quote($bbcode_match, '!'); + $fp_replace = preg_replace('#^\[(.*?)\]#', '[$1:$uid]', $bbcode_match); + $fp_replace = preg_replace('#\[/(.*?)\]$#', '[/$1:$uid]', $fp_replace); + + $sp_match = preg_quote($bbcode_match, '!'); + $sp_match = preg_replace('#^\\\\\[(.*?)\\\\\]#', '\[$1:$uid\]', $sp_match); + $sp_match = preg_replace('#\\\\\[/(.*?)\\\\\]$#', '\[/$1:$uid\]', $sp_match); + $sp_replace = $bbcode_tpl; + + // @todo Make sure to change this too if something changed in message parsing + $tokens = array( + 'URL' => array( + '!(?:(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))!ie' => "\$this->bbcode_specialchars(('\$1') ? '\$1' : 'http://\$2')" + ), + 'LOCAL_URL' => array( + '!(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')!e' => "\$this->bbcode_specialchars('$1')" + ), + 'EMAIL' => array( + '!(' . get_preg_expression('email') . ')!ie' => "\$this->bbcode_specialchars('$1')" + ), + 'TEXT' => array( + '!(.*?)!es' => "str_replace(array(\"\\r\\n\", '\\\"', '\\'', '(', ')'), array(\"\\n\", '\"', ''', '(', ')'), trim('\$1'))" + ), + 'SIMPLETEXT' => array( + '!([a-zA-Z0-9-+.,_ ]+)!' => "$1" + ), + 'IDENTIFIER' => array( + '!([a-zA-Z0-9-_]+)!' => "$1" + ), + 'COLOR' => array( + '!([a-z]+|#[0-9abcdef]+)!i' => '$1' + ), + 'NUMBER' => array( + '!([0-9]+)!' => '$1' + ) + ); + + $sp_tokens = array( + 'URL' => '(?i)((?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('url')) . ')|(?:' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('www_url')) . '))(?-i)', + 'LOCAL_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)', + 'EMAIL' => '(' . get_preg_expression('email') . ')', + 'TEXT' => '(.*?)', + 'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)', + 'IDENTIFIER' => '([a-zA-Z0-9-_]+)', + 'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)', + 'NUMBER' => '([0-9]+)', + ); + + $pad = 0; + $modifiers = 'i'; + + if (preg_match_all('/\{(' . implode('|', array_keys($tokens)) . ')[0-9]*\}/i', $bbcode_match, $m)) + { + foreach ($m[0] as $n => $token) + { + $token_type = $m[1][$n]; + + reset($tokens[strtoupper($token_type)]); + list($match, $replace) = each($tokens[strtoupper($token_type)]); + + // Pad backreference numbers from tokens + if (preg_match_all('/(?<!\\\\)\$([0-9]+)/', $replace, $repad)) + { + $repad = $pad + sizeof(array_unique($repad[0])); + $replace = preg_replace('/(?<!\\\\)\$([0-9]+)/e', "'\${' . (\$1 + \$pad) . '}'", $replace); + $pad = $repad; + } + + // Obtain pattern modifiers to use and alter the regex accordingly + $regex = preg_replace('/!(.*)!([a-z]*)/', '$1', $match); + $regex_modifiers = preg_replace('/!(.*)!([a-z]*)/', '$2', $match); + + for ($i = 0, $size = strlen($regex_modifiers); $i < $size; ++$i) + { + if (strpos($modifiers, $regex_modifiers[$i]) === false) + { + $modifiers .= $regex_modifiers[$i]; + + if ($regex_modifiers[$i] == 'e') + { + $fp_replace = "'" . str_replace("'", "\\'", $fp_replace) . "'"; + } + } + + if ($regex_modifiers[$i] == 'e') + { + $replace = "'.$replace.'"; + } + } + + $fp_match = str_replace(preg_quote($token, '!'), $regex, $fp_match); + $fp_replace = str_replace($token, $replace, $fp_replace); + + $sp_match = str_replace(preg_quote($token, '!'), $sp_tokens[$token_type], $sp_match); + $sp_replace = str_replace($token, '${' . ($n + 1) . '}', $sp_replace); + } + + $fp_match = '!' . $fp_match . '!' . $modifiers; + $sp_match = '!' . $sp_match . '!s'; + + if (strpos($fp_match, 'e') !== false) + { + $fp_replace = str_replace("'.'", '', $fp_replace); + $fp_replace = str_replace(".''.", '.', $fp_replace); + } + } + else + { + // No replacement is present, no need for a second-pass pattern replacement + // A simple str_replace will suffice + $fp_match = '!' . $fp_match . '!' . $modifiers; + $sp_match = $fp_replace; + $sp_replace = ''; + } + + // Lowercase tags + $bbcode_tag = preg_replace('/.*?\[([a-z0-9_-]+=?).*/i', '$1', $bbcode_match); + $bbcode_search = preg_replace('/.*?\[([a-z0-9_-]+)=?.*/i', '$1', $bbcode_match); + + if (!preg_match('/^[a-zA-Z0-9_-]+=?$/', $bbcode_tag)) + { + global $user; + trigger_error($user->lang['BBCODE_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $fp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_match); + $fp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $fp_replace); + $sp_match = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_match); + $sp_replace = preg_replace('#\[/?' . $bbcode_search . '#ie', "strtolower('\$0')", $sp_replace); + + return array( + 'bbcode_tag' => $bbcode_tag, + 'first_pass_match' => $fp_match, + 'first_pass_replace' => $fp_replace, + 'second_pass_match' => $sp_match, + 'second_pass_replace' => $sp_replace + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_board.php b/phpBB/modules/acp/acp_board.php new file mode 100644 index 0000000000..46ad90e546 --- /dev/null +++ b/phpBB/modules/acp/acp_board.php @@ -0,0 +1,828 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +* @todo add cron intervals to server settings? (database_gc, queue_interval, session_gc, search_gc, cache_gc, warnings_gc) +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_board +{ + var $u_action; + var $new_config = array(); + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $user->add_lang('acp/board'); + + $action = request_var('action', ''); + $submit = request::is_set_post('submit'); + + $form_key = 'acp_board'; + add_form_key($form_key); + + /** + * Validation types are: + * string, int, bool, + * script_path (absolute path in url - beginning with / and no trailing slash), + * rpath (relative), rwpath (realtive, writable), path (relative path, but able to escape the root), wpath (writable) + */ + switch ($mode) + { + case 'settings': + $display_vars = array( + 'title' => 'ACP_BOARD_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_BOARD_SETTINGS', + 'sitename' => array('lang' => 'SITE_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), + 'site_desc' => array('lang' => 'SITE_DESC', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => false), + 'board_disable' => array('lang' => 'DISABLE_BOARD', 'validate' => 'bool', 'type' => 'custom', 'method' => 'board_disable', 'explain' => true), + 'board_disable_msg' => false, + 'default_lang' => array('lang' => 'DEFAULT_LANGUAGE', 'validate' => 'lang', 'type' => 'select', 'function' => 'language_select', 'params' => array('{CONFIG_VALUE}'), 'explain' => false), + 'default_dateformat' => array('lang' => 'DEFAULT_DATE_FORMAT', 'validate' => 'string', 'type' => 'custom', 'method' => 'dateformat_select', 'explain' => true), + 'board_timezone' => array('lang' => 'SYSTEM_TIMEZONE', 'validate' => 'string', 'type' => 'select', 'function' => 'tz_select', 'params' => array('{CONFIG_VALUE}', 1), 'explain' => false), + 'board_dst' => array('lang' => 'SYSTEM_DST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'default_style' => array('lang' => 'DEFAULT_STYLE', 'validate' => 'int', 'type' => 'select', 'function' => 'style_select', 'params' => array('{CONFIG_VALUE}', false), 'explain' => false), + 'override_user_style' => array('lang' => 'OVERRIDE_STYLE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'WARNINGS', + 'warnings_expire_days' => array('lang' => 'WARNINGS_EXPIRE', 'validate' => 'int', 'type' => 'text:3:4', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + ) + ); + break; + + case 'features': + $display_vars = array( + 'title' => 'ACP_BOARD_FEATURES', + 'vars' => array( + 'legend1' => 'ACP_BOARD_FEATURES', + 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_attachments' => array('lang' => 'ALLOW_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_birthdays' => array('lang' => 'ALLOW_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'ACP_LOAD_SETTINGS', + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + ) + ); + break; + + case 'avatar': + $display_vars = array( + 'title' => 'ACP_AVATAR_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_AVATAR_SETTINGS', + 'avatar_min_height' => false, 'avatar_min_width' => false, 'avatar_max_height' => false, 'avatar_max_width' => false, + + 'allow_avatar_local' => array('lang' => 'ALLOW_LOCAL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_avatar_remote' => array('lang' => 'ALLOW_REMOTE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_avatar_upload' => array('lang' => 'ALLOW_UPLOAD', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'avatar_filesize' => array('lang' => 'MAX_FILESIZE', 'validate' => 'int:0', 'type' => 'text:4:10', 'explain' => true, 'append' => ' ' . $user->lang['BYTES']), + 'avatar_min' => array('lang' => 'MIN_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'avatar_max' => array('lang' => 'MAX_AVATAR_SIZE', 'validate' => 'int:0', 'type' => 'dimension:3:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'avatar_path' => array('lang' => 'AVATAR_STORAGE_PATH', 'validate' => 'rwpath', 'type' => 'text:20:255', 'explain' => true), + 'avatar_gallery_path' => array('lang' => 'AVATAR_GALLERY_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true) + ) + ); + break; + + case 'message': + $display_vars = array( + 'title' => 'ACP_MESSAGE_SETTINGS', + 'lang' => 'ucp', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'allow_privmsg' => array('lang' => 'BOARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'pm_max_boxes' => array('lang' => 'BOXES_MAX', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'pm_max_msgs' => array('lang' => 'BOXES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'full_folder_action' => array('lang' => 'FULL_FOLDER_ACTION', 'validate' => 'int', 'type' => 'select', 'method' => 'full_folder_select', 'explain' => true), + 'pm_edit_time' => array('lang' => 'PM_EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'pm_max_recipients' => array('lang' => 'PM_MAX_RECIPIENTS', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + + 'legend2' => 'GENERAL_OPTIONS', + 'allow_mass_pm' => array('lang' => 'ALLOW_MASS_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_bbcode_pm' => array('lang' => 'ALLOW_BBCODE_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_smilies_pm' => array('lang' => 'ALLOW_SMILIES_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_pm_attach' => array('lang' => 'ALLOW_PM_ATTACHMENTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_pm' => array('lang' => 'ALLOW_SIG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'print_pm' => array('lang' => 'ALLOW_PRINT_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'forward_pm' => array('lang' => 'ALLOW_FORWARD_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_img_pm' => array('lang' => 'ALLOW_IMG_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'auth_flash_pm' => array('lang' => 'ALLOW_FLASH_PM', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_pm_icons' => array('lang' => 'ENABLE_PM_ICONS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false) + ) + ); + break; + + case 'post': + $display_vars = array( + 'title' => 'ACP_POST_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_OPTIONS', + 'allow_topic_notify' => array('lang' => 'ALLOW_TOPIC_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_forum_notify' => array('lang' => 'ALLOW_FORUM_NOTIFY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_bbcode' => array('lang' => 'ALLOW_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_post_flash' => array('lang' => 'ALLOW_POST_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_smilies' => array('lang' => 'ALLOW_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_post_links' => array('lang' => 'ALLOW_POST_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_nocensors' => array('lang' => 'ALLOW_NO_CENSORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'allow_bookmarks' => array('lang' => 'ALLOW_BOOKMARKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_post_confirm' => array('lang' => 'VISUAL_CONFIRM_POST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'POSTING', + 'enable_queue_trigger' => array('lang' => 'ENABLE_QUEUE_TRIGGER', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'queue_trigger_posts' => array('lang' => 'QUEUE_TRIGGER_POSTS', 'validate' => 'int:0:250', 'type' => 'text:4:4', 'explain' => true), + 'bump_type' => false, + 'edit_time' => array('lang' => 'EDIT_TIME', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + 'display_last_edited' => array('lang' => 'DISPLAY_LAST_EDITED', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'flood_interval' => array('lang' => 'FLOOD_INTERVAL', 'validate' => 'int:0', 'type' => 'text:3:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'bump_interval' => array('lang' => 'BUMP_INTERVAL', 'validate' => 'int:0', 'type' => 'custom', 'method' => 'bump_interval', 'explain' => true), + 'topics_per_page' => array('lang' => 'TOPICS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false), + 'posts_per_page' => array('lang' => 'POSTS_PER_PAGE', 'validate' => 'int:1', 'type' => 'text:3:4', 'explain' => false), + 'hot_threshold' => array('lang' => 'HOT_THRESHOLD', 'validate' => 'int:0', 'type' => 'text:3:4', 'explain' => true), + 'max_poll_options' => array('lang' => 'MAX_POLL_OPTIONS', 'validate' => 'int:2:127', 'type' => 'text:4:4', 'explain' => false), + 'max_post_chars' => array('lang' => 'CHAR_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:6', 'explain' => true), + 'max_post_smilies' => array('lang' => 'SMILIES_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'max_post_urls' => array('lang' => 'MAX_POST_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_post_font_size' => array('lang' => 'MAX_POST_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), + 'max_quote_depth' => array('lang' => 'QUOTE_DEPTH_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'max_post_img_width' => array('lang' => 'MAX_POST_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'max_post_img_height' => array('lang' => 'MAX_POST_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + ) + ); + break; + + case 'signature': + $display_vars = array( + 'title' => 'ACP_SIGNATURE_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_OPTIONS', + 'allow_sig' => array('lang' => 'ALLOW_SIG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_bbcode' => array('lang' => 'ALLOW_SIG_BBCODE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_img' => array('lang' => 'ALLOW_SIG_IMG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_flash' => array('lang' => 'ALLOW_SIG_FLASH', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_smilies' => array('lang' => 'ALLOW_SIG_SMILIES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_sig_links' => array('lang' => 'ALLOW_SIG_LINKS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'GENERAL_SETTINGS', + 'max_sig_chars' => array('lang' => 'MAX_SIG_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_urls' => array('lang' => 'MAX_SIG_URLS', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_font_size' => array('lang' => 'MAX_SIG_FONT_SIZE', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' %'), + 'max_sig_smilies' => array('lang' => 'MAX_SIG_SMILIES', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true), + 'max_sig_img_width' => array('lang' => 'MAX_SIG_IMG_WIDTH', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + 'max_sig_img_height' => array('lang' => 'MAX_SIG_IMG_HEIGHT', 'validate' => 'int:0', 'type' => 'text:5:4', 'explain' => true, 'append' => ' ' . $user->lang['PIXEL']), + ) + ); + break; + + case 'registration': + $display_vars = array( + 'title' => 'ACP_REGISTER_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'max_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:8:180', 'type' => false, 'method' => false, 'explain' => false,), + 'max_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:8:255', 'type' => false, 'method' => false, 'explain' => false,), + + 'require_activation' => array('lang' => 'ACC_ACTIVATION', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_acc_activation', 'explain' => true), + 'min_name_chars' => array('lang' => 'USERNAME_LENGTH', 'validate' => 'int:1', 'type' => 'custom:5:180', 'method' => 'username_length', 'explain' => true), + 'min_pass_chars' => array('lang' => 'PASSWORD_LENGTH', 'validate' => 'int:1', 'type' => 'custom', 'method' => 'password_length', 'explain' => true), + 'allow_name_chars' => array('lang' => 'USERNAME_CHARS', 'validate' => 'string', 'type' => 'select', 'method' => 'select_username_chars', 'explain' => true), + 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), + 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + + 'legend2' => 'GENERAL_OPTIONS', + 'allow_namechange' => array('lang' => 'ALLOW_NAME_CHANGE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'allow_emailreuse' => array('lang' => 'ALLOW_EMAIL_REUSE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'enable_confirm' => array('lang' => 'VISUAL_CONFIRM_REG', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true), + 'max_reg_attempts' => array('lang' => 'REG_LIMIT', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + + 'legend3' => 'COPPA', + 'coppa_enable' => array('lang' => 'ENABLE_COPPA', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'coppa_mail' => array('lang' => 'COPPA_MAIL', 'validate' => 'string', 'type' => 'textarea:5:40', 'explain' => true), + 'coppa_fax' => array('lang' => 'COPPA_FAX', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => false), + ) + ); + break; + + case 'cookie': + $display_vars = array( + 'title' => 'ACP_COOKIE_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_COOKIE_SETTINGS', + 'cookie_domain' => array('lang' => 'COOKIE_DOMAIN', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), + 'cookie_name' => array('lang' => 'COOKIE_NAME', 'validate' => 'string', 'type' => 'text::16', 'explain' => false), + 'cookie_path' => array('lang' => 'COOKIE_PATH', 'validate' => 'string', 'type' => 'text::255', 'explain' => false), + 'cookie_secure' => array('lang' => 'COOKIE_SECURE', 'validate' => 'bool', 'type' => 'radio:disabled_enabled', 'explain' => true) + ) + ); + break; + + case 'load': + $display_vars = array( + 'title' => 'ACP_LOAD_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'limit_load' => array('lang' => 'LIMIT_LOAD', 'validate' => 'string', 'type' => 'text:4:4', 'explain' => true), + 'session_length' => array('lang' => 'SESSION_LENGTH', 'validate' => 'int:60', 'type' => 'text:5:10', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'active_sessions' => array('lang' => 'LIMIT_SESSIONS', 'validate' => 'int:0', 'type' => 'text:4:4', 'explain' => true), + 'load_online_time' => array('lang' => 'ONLINE_LENGTH', 'validate' => 'int:0', 'type' => 'text:4:3', 'explain' => true, 'append' => ' ' . $user->lang['MINUTES']), + + 'legend2' => 'GENERAL_OPTIONS', + 'load_db_track' => array('lang' => 'YES_POST_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_db_lastread' => array('lang' => 'YES_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_anon_lastread' => array('lang' => 'YES_ANON_READ_MARKING', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online' => array('lang' => 'YES_ONLINE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_online_guests' => array('lang' => 'YES_ONLINE_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_onlinetrack' => array('lang' => 'YES_ONLINE_TRACK', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_birthdays' => array('lang' => 'YES_BIRTHDAYS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_moderators' => array('lang' => 'YES_MODERATORS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_jumpbox' => array('lang' => 'YES_JUMPBOX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_user_activity' => array('lang' => 'LOAD_USER_ACTIVITY', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'load_tplcompile' => array('lang' => 'RECOMPILE_STYLES', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend3' => 'CUSTOM_PROFILE_FIELDS', + 'load_cpf_memberlist' => array('lang' => 'LOAD_CPF_MEMBERLIST', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewprofile' => array('lang' => 'LOAD_CPF_VIEWPROFILE', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + 'load_cpf_viewtopic' => array('lang' => 'LOAD_CPF_VIEWTOPIC', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => false), + ) + ); + break; + + case 'auth': + $display_vars = array( + 'title' => 'ACP_AUTH_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_AUTH_SETTINGS', + 'auth_method' => array('lang' => 'AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'select_auth_method', 'explain' => false) + ) + ); + break; + + case 'server': + $display_vars = array( + 'title' => 'ACP_SERVER_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_SERVER_SETTINGS', + 'gzip_compress' => array('lang' => 'ENABLE_GZIP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'PATH_SETTINGS', + 'smilies_path' => array('lang' => 'SMILIES_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'icons_path' => array('lang' => 'ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'upload_icons_path' => array('lang' => 'UPLOAD_ICONS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + 'ranks_path' => array('lang' => 'RANKS_PATH', 'validate' => 'rpath', 'type' => 'text:20:255', 'explain' => true), + + 'legend3' => 'SERVER_URL_SETTINGS', + 'force_server_vars' => array('lang' => 'FORCE_SERVER_VARS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'server_protocol' => array('lang' => 'SERVER_PROTOCOL', 'validate' => 'string', 'type' => 'text:10:10', 'explain' => true), + 'server_name' => array('lang' => 'SERVER_NAME', 'validate' => 'string', 'type' => 'text:40:255', 'explain' => true), + 'server_port' => array('lang' => 'SERVER_PORT', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + 'script_path' => array('lang' => 'SCRIPT_PATH', 'validate' => 'script_path', 'type' => 'text::255', 'explain' => true), + ) + ); + break; + + case 'security': + $display_vars = array( + 'title' => 'ACP_SECURITY_SETTINGS', + 'vars' => array( + 'legend1' => 'ACP_SECURITY_SETTINGS', + 'allow_autologin' => array('lang' => 'ALLOW_AUTOLOGIN', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'max_autologin_time' => array('lang' => 'AUTOLOGIN_LENGTH', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + 'ip_check' => array('lang' => 'IP_VALID', 'validate' => 'int', 'type' => 'custom', 'method' => 'select_ip_check', 'explain' => true), + 'browser_check' => array('lang' => 'BROWSER_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'forwarded_for_check' => array('lang' => 'FORWARDED_FOR_VALID', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'referer_validation' => array('lang' => 'REFERER_VALID', 'validate' => 'int:0:3','type' => 'custom', 'method' => 'select_ref_check', 'explain' => true), + 'check_dnsbl' => array('lang' => 'CHECK_DNSBL', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'email_check_mx' => array('lang' => 'EMAIL_CHECK_MX', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'pass_complex' => array('lang' => 'PASSWORD_TYPE', 'validate' => 'string', 'type' => 'select', 'method' => 'select_password_chars', 'explain' => true), + 'chg_passforce' => array('lang' => 'FORCE_PASS_CHANGE', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true, 'append' => ' ' . $user->lang['DAYS']), + 'max_login_attempts' => array('lang' => 'MAX_LOGIN_ATTEMPTS', 'validate' => 'int:0', 'type' => 'text:3:3', 'explain' => true), + 'tpl_allow_php' => array('lang' => 'TPL_ALLOW_PHP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'form_token_lifetime' => array('lang' => 'FORM_TIME_MAX', 'validate' => 'int:-1', 'type' => 'text:5:5', 'explain' => true, 'append' => ' ' . $user->lang['SECONDS']), + 'form_token_sid_guests' => array('lang' => 'FORM_SID_GUESTS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + ) + ); + break; + + case 'email': + $display_vars = array( + 'title' => 'ACP_EMAIL_SETTINGS', + 'vars' => array( + 'legend1' => 'GENERAL_SETTINGS', + 'email_enable' => array('lang' => 'ENABLE_EMAIL', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'board_email_form' => array('lang' => 'BOARD_EMAIL_FORM', 'validate' => 'bool', 'type' => 'radio:enabled_disabled', 'explain' => true), + 'email_function_name' => array('lang' => 'EMAIL_FUNCTION_NAME', 'validate' => 'string', 'type' => 'text:20:50', 'explain' => true), + 'email_package_size' => array('lang' => 'EMAIL_PACKAGE_SIZE', 'validate' => 'int:0', 'type' => 'text:5:5', 'explain' => true), + 'board_contact' => array('lang' => 'CONTACT_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), + 'board_email' => array('lang' => 'ADMIN_EMAIL', 'validate' => 'string', 'type' => 'text:25:100', 'explain' => true), + 'board_email_sig' => array('lang' => 'EMAIL_SIG', 'validate' => 'string', 'type' => 'textarea:5:30', 'explain' => true), + 'board_hide_emails' => array('lang' => 'BOARD_HIDE_EMAILS', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + + 'legend2' => 'SMTP_SETTINGS', + 'smtp_delivery' => array('lang' => 'USE_SMTP', 'validate' => 'bool', 'type' => 'radio:yes_no', 'explain' => true), + 'smtp_host' => array('lang' => 'SMTP_SERVER', 'validate' => 'string', 'type' => 'text:25:50', 'explain' => false), + 'smtp_port' => array('lang' => 'SMTP_PORT', 'validate' => 'int:0', 'type' => 'text:4:5', 'explain' => true), + 'smtp_auth_method' => array('lang' => 'SMTP_AUTH_METHOD', 'validate' => 'string', 'type' => 'select', 'method' => 'mail_auth_select', 'explain' => true), + 'smtp_username' => array('lang' => 'SMTP_USERNAME', 'validate' => 'string', 'type' => 'text:25:255', 'explain' => true), + 'smtp_password' => array('lang' => 'SMTP_PASSWORD', 'validate' => 'string', 'type' => 'password:25:255', 'explain' => true) + ) + ); + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + if (isset($display_vars['lang'])) + { + $user->add_lang($display_vars['lang']); + } + + $this->new_config = $config; + $cfg_array = (request::is_set('config')) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config; + $error = array(); + + // We validate the complete config if whished + validate_config_vars($display_vars['vars'], $cfg_array, $error); + + if ($submit && !check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Do not write values if there is an error + if (sizeof($error)) + { + $submit = false; + } + + // We go through the display_vars to make sure no one is trying to set variables he/she is not allowed to... + foreach ($display_vars['vars'] as $config_name => $null) + { + if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false) + { + continue; + } + + if ($config_name == 'auth_method') + { + continue; + } + + $this->new_config[$config_name] = $config_value = $cfg_array[$config_name]; + + if ($config_name == 'email_function_name') + { + $this->new_config['email_function_name'] = trim(str_replace(array('(', ')'), array('', ''), $this->new_config['email_function_name'])); + $this->new_config['email_function_name'] = (empty($this->new_config['email_function_name']) || !function_exists($this->new_config['email_function_name'])) ? 'mail' : $this->new_config['email_function_name']; + $config_value = $this->new_config['email_function_name']; + } + + if ($submit) + { + set_config($config_name, $config_value); + } + } + + if ($mode == 'auth') + { + // Retrieve a list of auth plugins and check their config values + $auth_plugins = array(); + + $dp = @opendir(PHPBB_ROOT_PATH . 'includes/auth'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if (preg_match('#^auth_(.*?)\.' . PHP_EXT . '$#', $file)) + { + $auth_plugins[] = basename(preg_replace('#^auth_(.*?)\.' . PHP_EXT . '$#', '\1', $file)); + } + } + closedir($dp); + + sort($auth_plugins); + } + + $updated_auth_settings = false; + $old_auth_config = array(); + foreach ($auth_plugins as $method) + { + if ($method && file_exists(PHPBB_ROOT_PATH . 'includes/auth/auth_' . $method . '.' . PHP_EXT)) + { + include_once(PHPBB_ROOT_PATH . 'includes/auth/auth_' . $method . '.' . PHP_EXT); + + $method = 'acp_' . $method; + if (function_exists($method)) + { + if ($fields = $method($this->new_config)) + { + // Check if we need to create config fields for this plugin and save config when submit was pressed + foreach ($fields['config'] as $field) + { + if (!isset($config[$field])) + { + set_config($field, ''); + } + + if (!isset($cfg_array[$field]) || strpos($field, 'legend') !== false) + { + continue; + } + + $old_auth_config[$field] = $this->new_config[$field]; + $config_value = $cfg_array[$field]; + $this->new_config[$field] = $config_value; + + if ($submit) + { + $updated_auth_settings = true; + set_config($field, $config_value); + } + } + } + unset($fields); + } + } + } + + if ($submit && (($cfg_array['auth_method'] != $this->new_config['auth_method']) || $updated_auth_settings)) + { + $method = basename($cfg_array['auth_method']); + if ($method && in_array($method, $auth_plugins)) + { + include_once(PHPBB_ROOT_PATH . 'includes/auth/auth_' . $method . '.' . PHP_EXT); + + $method = 'init_' . $method; + if (function_exists($method)) + { + if ($error = $method()) + { + foreach ($old_auth_config as $config_name => $config_value) + { + set_config($config_name, $config_value); + } + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + set_config('auth_method', basename($cfg_array['auth_method'])); + } + else + { + trigger_error('NO_AUTH_PLUGIN', E_USER_ERROR); + } + } + } + + if ($submit) + { + add_log('admin', 'LOG_CONFIG_' . strtoupper($mode)); + + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + + $this->tpl_name = 'acp_board'; + $this->page_title = $display_vars['title']; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$display_vars['title']], + 'L_TITLE_EXPLAIN' => $user->lang[$display_vars['title'] . '_EXPLAIN'], + + 'S_ERROR' => (sizeof($error)) ? true : false, + 'ERROR_MSG' => implode('<br />', $error), + + 'U_ACTION' => $this->u_action) + ); + + // Output relevant page + foreach ($display_vars['vars'] as $config_key => $vars) + { + if (!is_array($vars) && strpos($config_key, 'legend') === false) + { + continue; + } + + if (strpos($config_key, 'legend') !== false) + { + $template->assign_block_vars('options', array( + 'S_LEGEND' => true, + 'LEGEND' => (isset($user->lang[$vars])) ? $user->lang[$vars] : $vars) + ); + + continue; + } + + $type = explode(':', $vars['type']); + + $l_explain = ''; + if ($vars['explain'] && isset($vars['lang_explain'])) + { + $l_explain = (isset($user->lang[$vars['lang_explain']])) ? $user->lang[$vars['lang_explain']] : $vars['lang_explain']; + } + else if ($vars['explain']) + { + $l_explain = (isset($user->lang[$vars['lang'] . '_EXPLAIN'])) ? $user->lang[$vars['lang'] . '_EXPLAIN'] : ''; + } + + $content = build_cfg_template($type, $config_key, $this->new_config, $config_key, $vars); + + if (empty($content)) + { + continue; + } + + $template->assign_block_vars('options', array( + 'KEY' => $config_key, + 'TITLE' => (isset($user->lang[$vars['lang']])) ? $user->lang[$vars['lang']] : $vars['lang'], + 'S_EXPLAIN' => $vars['explain'], + 'TITLE_EXPLAIN' => $l_explain, + 'CONTENT' => $content, + ) + ); + + unset($display_vars['vars'][$config_key]); + } + + if ($mode == 'auth') + { + $template->assign_var('S_AUTH', true); + + foreach ($auth_plugins as $method) + { + if ($method && file_exists(PHPBB_ROOT_PATH . 'includes/auth/auth_' . $method . '.' . PHP_EXT)) + { + $method = 'acp_' . $method; + if (function_exists($method)) + { + $fields = $method($this->new_config); + + if ($fields['tpl']) + { + $template->assign_block_vars('auth_tpl', array( + 'TPL' => $fields['tpl']) + ); + } + unset($fields); + } + } + } + } + } + + /** + * Select auth method + */ + function select_auth_method($selected_method, $key = '') + { + $auth_plugins = array(); + + $dp = @opendir(PHPBB_ROOT_PATH . 'includes/auth'); + + if (!$dp) + { + return ''; + } + + while (($file = readdir($dp)) !== false) + { + if (preg_match('#^auth_(.*?)\.' . PHP_EXT . '$#', $file)) + { + $auth_plugins[] = preg_replace('#^auth_(.*?)\.' . PHP_EXT . '$#', '\1', $file); + } + } + closedir($dp); + + sort($auth_plugins); + + $auth_select = ''; + foreach ($auth_plugins as $method) + { + $selected = ($selected_method == $method) ? ' selected="selected"' : ''; + $auth_select .= '<option value="' . $method . '"' . $selected . '>' . ucfirst($method) . '</option>'; + } + + return $auth_select; + } + + /** + * Select mail authentication method + */ + function mail_auth_select($selected_method, $key = '') + { + global $user; + + $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5', 'POP-BEFORE-SMTP'); + $s_smtp_auth_options = ''; + + foreach ($auth_methods as $method) + { + $s_smtp_auth_options .= '<option value="' . $method . '"' . (($selected_method == $method) ? ' selected="selected"' : '') . '>' . $user->lang['SMTP_' . str_replace('-', '_', $method)] . '</option>'; + } + + return $s_smtp_auth_options; + } + + /** + * Select full folder action + */ + function full_folder_select($value, $key = '') + { + global $user; + + return '<option value="1"' . (($value == 1) ? ' selected="selected"' : '') . '>' . $user->lang['DELETE_OLDEST_MESSAGES'] . '</option><option value="2"' . (($value == 2) ? ' selected="selected"' : '') . '>' . $user->lang['HOLD_NEW_MESSAGES_SHORT'] . '</option>'; + } + + /** + * Select ip validation + */ + function select_ip_check($value, $key = '') + { + $radio_ary = array(4 => 'ALL', 3 => 'CLASS_C', 2 => 'CLASS_B', 0 => 'NO_IP_VALIDATION'); + + return h_radio('config[ip_check]', $radio_ary, $value, $key); + } + + /** + * Select referer validation + */ + function select_ref_check($value, $key = '') + { + $radio_ary = array(REFERER_VALIDATE_PATH => 'REF_PATH', REFERER_VALIDATE_HOST => 'REF_HOST', REFERER_VALIDATE_NONE => 'NO_REF_VALIDATION'); + + return h_radio('config[referer_validation]', $radio_ary, $value, $key); + } + + /** + * Select account activation method + */ + function select_acc_activation($value, $key = '') + { + global $user, $config; + + $radio_ary = array(USER_ACTIVATION_DISABLE => 'ACC_DISABLE', USER_ACTIVATION_NONE => 'ACC_NONE'); + if ($config['email_enable']) + { + $radio_ary += array(USER_ACTIVATION_SELF => 'ACC_USER', USER_ACTIVATION_ADMIN => 'ACC_ADMIN'); + } + + return h_radio('config[require_activation]', $radio_ary, $value, $key); + } + + /** + * Maximum/Minimum username length + */ + function username_length($value, $key = '') + { + global $user; + + return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_name_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . ' <input type="text" size="3" maxlength="3" name="config[max_name_chars]" value="' . $this->new_config['max_name_chars'] . '" /> ' . $user->lang['MAX_CHARS']; + } + + /** + * Allowed chars in usernames + */ + function select_username_chars($selected_value, $key) + { + global $user; + + $user_char_ary = array('USERNAME_CHARS_ANY', 'USERNAME_ALPHA_ONLY', 'USERNAME_ALPHA_SPACERS', 'USERNAME_LETTER_NUM', 'USERNAME_LETTER_NUM_SPACERS', 'USERNAME_ASCII'); + $user_char_options = ''; + foreach ($user_char_ary as $user_type) + { + $selected = ($selected_value == $user_type) ? ' selected="selected"' : ''; + $user_char_options .= '<option value="' . $user_type . '"' . $selected . '>' . $user->lang[$user_type] . '</option>'; + } + + return $user_char_options; + } + + /** + * Maximum/Minimum password length + */ + function password_length($value, $key) + { + global $user; + + return '<input id="' . $key . '" type="text" size="3" maxlength="3" name="config[min_pass_chars]" value="' . $value . '" /> ' . $user->lang['MIN_CHARS'] . ' <input type="text" size="3" maxlength="3" name="config[max_pass_chars]" value="' . $this->new_config['max_pass_chars'] . '" /> ' . $user->lang['MAX_CHARS']; + } + + /** + * Required chars in passwords + */ + function select_password_chars($selected_value, $key) + { + global $user; + + $pass_type_ary = array('PASS_TYPE_ANY', 'PASS_TYPE_CASE', 'PASS_TYPE_ALPHA', 'PASS_TYPE_SYMBOL'); + $pass_char_options = ''; + foreach ($pass_type_ary as $pass_type) + { + $selected = ($selected_value == $pass_type) ? ' selected="selected"' : ''; + $pass_char_options .= '<option value="' . $pass_type . '"' . $selected . '>' . $user->lang[$pass_type] . '</option>'; + } + + return $pass_char_options; + } + + /** + * Select bump interval + */ + function bump_interval($value, $key) + { + global $user; + + $s_bump_type = ''; + $types = array('m' => 'MINUTES', 'h' => 'HOURS', 'd' => 'DAYS'); + foreach ($types as $type => $lang) + { + $selected = ($this->new_config['bump_type'] == $type) ? ' selected="selected"' : ''; + $s_bump_type .= '<option value="' . $type . '"' . $selected . '>' . $user->lang[$lang] . '</option>'; + } + + return '<input id="' . $key . '" type="text" size="3" maxlength="4" name="config[bump_interval]" value="' . $value . '" /> <select name="config[bump_type]">' . $s_bump_type . '</select>'; + } + + /** + * Board disable option and message + */ + function board_disable($value, $key) + { + global $user; + + $radio_ary = array(1 => 'YES', 0 => 'NO'); + + return h_radio('config[board_disable]', $radio_ary, $value) . '<br /><input id="' . $key . '" type="text" name="config[board_disable_msg]" maxlength="255" size="40" value="' . $this->new_config['board_disable_msg'] . '" />'; + } + + /** + * Select default dateformat + */ + function dateformat_select($value, $key) + { + global $user, $config; + + // Let the format_date function operate with the acp values + $old_tz = $user->timezone; + $old_dst = $user->dst; + + $user->timezone = $config['board_timezone']; + $user->dst = $config['board_dst']; + + $dateformat_options = ''; + + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $value) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$value])) + { + $dateformat_options .= ' selected="selected"'; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + // Reset users date options + $user->timezone = $old_tz; + $user->dst = $old_dst; + + return "<select name=\"dateoptions\" id=\"dateoptions\" onchange=\"if (this.value == 'custom') { document.getElementById('" . addslashes($key) . "').value = '" . addslashes($value) . "'; } else { document.getElementById('" . addslashes($key) . "').value = this.value; }\">$dateformat_options</select> + <input type=\"text\" name=\"config[$key]\" id=\"$key\" value=\"$value\" maxlength=\"30\" />"; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_bots.php b/phpBB/modules/acp/acp_bots.php new file mode 100644 index 0000000000..327b31968d --- /dev/null +++ b/phpBB/modules/acp/acp_bots.php @@ -0,0 +1,417 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_bots +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + $action = request_var('action', ''); + $submit = request::is_set_post('submit'); + $mark = request_var('mark', array(0)); + $bot_id = request_var('id', 0); + + if (request::is_set_post('add')) + { + $action = 'add'; + } + + $error = array(); + + $user->add_lang('acp/bots'); + $this->tpl_name = 'acp_bots'; + $this->page_title = 'ACP_BOTS'; + $form_key = 'acp_bots'; + add_form_key($form_key); + + if ($submit && !check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + + // User wants to do something, how inconsiderate of them! + switch ($action) + { + case 'activate': + if ($bot_id || sizeof($mark)) + { + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'UPDATE ' . BOTS_TABLE . " + SET bot_active = 1 + WHERE bot_id $sql_id"; + $db->sql_query($sql); + } + + $cache->destroy('_bots'); + break; + + case 'deactivate': + if ($bot_id || sizeof($mark)) + { + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'UPDATE ' . BOTS_TABLE . " + SET bot_active = 0 + WHERE bot_id $sql_id"; + $db->sql_query($sql); + } + + $cache->destroy('_bots'); + break; + + case 'delete': + if ($bot_id || sizeof($mark)) + { + if (confirm_box(true)) + { + // We need to delete the relevant user, usergroup and bot entries ... + $sql_id = ($bot_id) ? " = $bot_id" : ' IN (' . implode(', ', $mark) . ')'; + + $sql = 'SELECT bot_name, user_id + FROM ' . BOTS_TABLE . " + WHERE bot_id $sql_id"; + $result = $db->sql_query($sql); + + $user_id_ary = $bot_name_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_id_ary[] = (int) $row['user_id']; + $bot_name_ary[] = $row['bot_name']; + } + $db->sql_freeresult($result); + + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . BOTS_TABLE . " + WHERE bot_id $sql_id"; + $db->sql_query($sql); + + if (sizeof($user_id_ary)) + { + $_tables = array(USERS_TABLE, USER_GROUP_TABLE); + foreach ($_tables as $table) + { + $sql = "DELETE FROM $table + WHERE " . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + $cache->destroy('_bots'); + + add_log('admin', 'LOG_BOT_DELETE', implode(', ', $bot_name_ary)); + trigger_error($user->lang['BOT_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark, + 'id' => $bot_id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + break; + + case 'edit': + case 'add': + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $bot_row = array( + 'bot_name' => utf8_normalize_nfc(request_var('bot_name', '', true)), + 'bot_agent' => request_var('bot_agent', ''), + 'bot_ip' => request_var('bot_ip', ''), + 'bot_active' => request_var('bot_active', true), + 'bot_lang' => request_var('bot_lang', $config['default_lang']), + 'bot_style' => request_var('bot_style' , $config['default_style']), + ); + + if ($submit) + { + if (!$bot_row['bot_agent'] && !$bot_row['bot_ip']) + { + $error[] = $user->lang['ERR_BOT_NO_MATCHES']; + } + + if ($bot_row['bot_ip'] && !preg_match('#^[\d\.,:]+$#', $bot_row['bot_ip'])) + { + if (!$ip_list = gethostbynamel($bot_row['bot_ip'])) + { + $error[] = $user->lang['ERR_BOT_NO_IP']; + } + else + { + $bot_row['bot_ip'] = implode(',', $ip_list); + } + } + $bot_row['bot_ip'] = str_replace(' ', '', $bot_row['bot_ip']); + + // Make sure the admin is not adding a bot with an user agent similar to his one + if ($bot_row['bot_agent'] && substr($user->data['session_browser'], 0, 149) === substr($bot_row['bot_agent'], 0, 149)) + { + $error[] = $user->lang['ERR_BOT_AGENT_MATCHES_UA']; + } + + $bot_name = false; + if ($bot_id) + { + $sql = 'SELECT u.username_clean + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u + WHERE b.bot_id = $bot_id + AND u.user_id = b.user_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$bot_row) + { + $error[] = $user->lang['NO_BOT']; + } + else + { + $bot_name = $row['username_clean']; + } + } + if (!$this->validate_botname($bot_row['bot_name'], $bot_name)) + { + $error[] = $user->lang['BOT_NAME_TAKEN']; + } + + if (!sizeof($error)) + { + // New bot? Create a new user and group entry + if ($action == 'add') + { + $sql = 'SELECT group_id, group_colour + FROM ' . GROUPS_TABLE . " + WHERE group_name_clean = 'bots' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_BOT_GROUP'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + + $user_id = user_add(array( + 'user_type' => (int) USER_IGNORE, + 'group_id' => (int) $group_row['group_id'], + 'username' => (string) $bot_row['bot_name'], + 'user_regdate' => time(), + 'user_password' => '', + 'user_colour' => (string) $group_row['group_colour'], + 'user_email' => '', + 'user_lang' => (string) $bot_row['bot_lang'], + 'user_style' => (int) $bot_row['bot_style'], + 'user_allow_massemail' => 0, + )); + + $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => (int) $user_id, + 'bot_name' => (string) $bot_row['bot_name'], + 'bot_active' => (int) $bot_row['bot_active'], + 'bot_agent' => (string) $bot_row['bot_agent'], + 'bot_ip' => (string) $bot_row['bot_ip']) + ); + $db->sql_query($sql); + + $log = 'ADDED'; + } + else if ($bot_id) + { + $sql = 'SELECT user_id, bot_name + FROM ' . BOTS_TABLE . " + WHERE bot_id = $bot_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + $sql_ary = array( + 'user_style' => (int) $bot_row['bot_style'], + 'user_lang' => (string) $bot_row['bot_lang'], + ); + + if ($bot_row['bot_name'] !== $row['bot_name']) + { + $sql_ary['username'] = (string) $bot_row['bot_name']; + $sql_ary['username_clean'] = (string) utf8_clean_string($bot_row['bot_name']); + } + + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE user_id = {$row['user_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . BOTS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', array( + 'bot_name' => (string) $bot_row['bot_name'], + 'bot_active' => (int) $bot_row['bot_active'], + 'bot_agent' => (string) $bot_row['bot_agent'], + 'bot_ip' => (string) $bot_row['bot_ip']) + ) . " WHERE bot_id = $bot_id"; + $db->sql_query($sql); + + // Updated username? + if ($bot_row['bot_name'] !== $row['bot_name']) + { + user_update_name($row['bot_name'], $bot_row['bot_name']); + } + + $log = 'UPDATED'; + } + + $cache->destroy('_bots'); + + add_log('admin', 'LOG_BOT_' . $log, $bot_row['bot_name']); + trigger_error($user->lang['BOT_' . $log] . adm_back_link($this->u_action)); + + } + } + else if ($bot_id) + { + $sql = 'SELECT b.*, u.user_lang, u.user_style + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . " u + WHERE b.bot_id = $bot_id + AND u.user_id = b.user_id"; + $result = $db->sql_query($sql); + $bot_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$bot_row) + { + trigger_error($user->lang['NO_BOT'] . adm_back_link($this->u_action . "&id=$bot_id&action=$action"), E_USER_WARNING); + } + + $bot_row['bot_lang'] = $bot_row['user_lang']; + $bot_row['bot_style'] = $bot_row['user_style']; + unset($bot_row['user_lang'], $bot_row['user_style']); + } + + $s_active_options = ''; + $_options = array('0' => 'NO', '1' => 'YES'); + foreach ($_options as $value => $lang) + { + $selected = ($bot_row['bot_active'] == $value) ? ' selected="selected"' : ''; + $s_active_options .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$lang] . '</option>'; + } + + $style_select = style_select($bot_row['bot_style'], true); + $lang_select = language_select($bot_row['bot_lang']); + + $l_title = ($action == 'edit') ? 'EDIT' : 'ADD'; + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['BOT_' . $l_title], + 'U_ACTION' => $this->u_action . "&id=$bot_id&action=$action", + 'U_BACK' => $this->u_action, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'BOT_NAME' => $bot_row['bot_name'], + 'BOT_IP' => $bot_row['bot_ip'], + 'BOT_AGENT' => $bot_row['bot_agent'], + + 'S_EDIT_BOT' => true, + 'S_ACTIVE_OPTIONS' => $s_active_options, + 'S_STYLE_OPTIONS' => $style_select, + 'S_LANG_OPTIONS' => $lang_select, + 'S_ERROR' => (sizeof($error)) ? true : false, + ) + ); + + return; + + break; + } + + $s_options = ''; + $_options = array('activate' => 'BOT_ACTIVATE', 'deactivate' => 'BOT_DEACTIVATE', 'delete' => 'DELETE'); + foreach ($_options as $value => $lang) + { + $s_options .= '<option value="' . $value . '">' . $user->lang[$lang] . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_BOT_OPTIONS' => $s_options) + ); + + $sql = 'SELECT b.bot_id, b.bot_name, b.bot_active, u.user_lastvisit + FROM ' . BOTS_TABLE . ' b, ' . USERS_TABLE . ' u + WHERE u.user_id = b.user_id + ORDER BY u.user_lastvisit DESC, b.bot_name ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $active_lang = (!$row['bot_active']) ? 'BOT_ACTIVATE' : 'BOT_DEACTIVATE'; + $active_value = (!$row['bot_active']) ? 'activate' : 'deactivate'; + + $template->assign_block_vars('bots', array( + 'BOT_NAME' => $row['bot_name'], + 'BOT_ID' => $row['bot_id'], + 'LAST_VISIT' => ($row['user_lastvisit']) ? $user->format_date($row['user_lastvisit']) : $user->lang['BOT_NEVER'], + + 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&id={$row['bot_id']}&action=$active_value", + 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang], + 'U_EDIT' => $this->u_action . "&id={$row['bot_id']}&action=edit", + 'U_DELETE' => $this->u_action . "&id={$row['bot_id']}&action=delete") + ); + } + $db->sql_freeresult($result); + } + + /** + * Validate bot name against username table + */ + function validate_botname($newname, $oldname = false) + { + global $db; + + if ($oldname && utf8_clean_string($newname) === $oldname) + { + return true; + } + + // Admins might want to use names otherwise forbidden, thus we only check for duplicates. + $sql = 'SELECT username + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($newname)) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + return ($row) ? false : true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_captcha.php b/phpBB/modules/acp/acp_captcha.php new file mode 100644 index 0000000000..dbc18e59bc --- /dev/null +++ b/phpBB/modules/acp/acp_captcha.php @@ -0,0 +1,144 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +*/ + +/** +* @ignore +*/ + + +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_captcha +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $user->add_lang('acp/board'); + + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + + $selected = request_var('select_captcha', $config['captcha_plugin']); + $configure = request_var('configure', false); + + // Oh, they are just here for the view + if (request::is_set('captcha_demo', request::GET)) + { + $this->deliver_demo($selected); + } + + // Delegate + if ($configure) + { + $config_captcha = phpbb_captcha_factory::get_instance($selected); + $config_captcha->acp_page($id, $this); + } + else + { + $captchas = phpbb_captcha_factory::get_captcha_types(); + + $config_vars = array( + 'enable_confirm' => 'REG_ENABLE', + 'enable_post_confirm' => 'POST_ENABLE', + ); + + $this->tpl_name = 'acp_captcha'; + $this->page_title = 'ACP_VC_SETTINGS'; + $form_key = 'acp_captcha'; + add_form_key($form_key); + + $submit = request_var('main_submit', false); + + if ($submit && check_form_key($form_key)) + { + $config_vars = array_keys($config_vars); + foreach ($config_vars as $config_var) + { + set_config($config_var, request_var($config_var, false)); + } + if ($selected !== $config['captcha_plugin']) + { + // sanity check + if (isset($captchas['available'][$selected])) + { + $old_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $old_captcha->uninstall(); + set_config('captcha_plugin', $selected); + $new_captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $new_captcha->install(); + } + else + { + trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action)); + } + } + trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action)); + } + else if ($submit) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link()); + } + else + { + $captcha_select = ''; + foreach ($captchas['available'] as $value => $title) + { + $current = ($selected !== false && $value == $selected) ? ' selected="selected"' : ''; + $captcha_select .= '<option value="' . $value . '"' . $current . '>' . $user->lang[$title] . '</option>'; + } + foreach ($captchas['unavailable'] as $value => $title) + { + $captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option" >' . $user->lang[$title] . '</option>'; + } + + $demo_captcha = phpbb_captcha_factory::get_instance($selected); + + foreach ($config_vars as $config_var => $template_var) + { + $template->assign_var($template_var, request_var($config_var, $config[$config_var])) ; + } + + $template->assign_vars(array( + 'CAPTCHA_PREVIEW' => $demo_captcha->get_demo_template($id), + 'CAPTCHA_SELECT' => $captcha_select, + )); + } + + } + } + + + /** + * Entry point for delivering image CAPTCHAs in the ACP. + */ + function deliver_demo($selected) + { + global $db, $user, $config; + + $captcha = phpbb_captcha_factory::get_instance($selected); + $captcha->init(CONFIRM_REG); + $captcha->execute_demo(); + garbage_collection(); + exit_handler(); + } + + + + +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_database.php b/phpBB/modules/acp/acp_database.php new file mode 100644 index 0000000000..b8115f5ed1 --- /dev/null +++ b/phpBB/modules/acp/acp_database.php @@ -0,0 +1,2357 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_database +{ + var $u_action; + + function main($id, $mode) + { + global $cache, $db, $user, $auth, $template, $table_prefix, $config; + + $user->add_lang('acp/database'); + + $this->tpl_name = 'acp_database'; + $this->page_title = 'ACP_DATABASE'; + + $action = request_var('action', ''); + $submit = request::is_set_post('submit'); + + $template->assign_vars(array( + 'MODE' => $mode + )); + + switch ($mode) + { + case 'backup': + + $this->page_title = 'ACP_BACKUP'; + + switch ($action) + { + case 'download': + $type = request_var('type', ''); + $table = request_var('table', array('')); + $format = request_var('method', ''); + $where = request_var('where', ''); + + if (!sizeof($table)) + { + trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $store = $download = $structure = $schema_data = false; + + if ($where == 'store_and_download' || $where == 'store') + { + $store = true; + } + + if ($where == 'store_and_download' || $where == 'download') + { + $download = true; + } + + if ($type == 'full' || $type == 'structure') + { + $structure = true; + } + + if ($type == 'full' || $type == 'data') + { + $schema_data = true; + } + + @set_time_limit(1200); + + $time = time(); + + $filename = 'backup_' . $time . '_' . unique_id(); + switch ($db->dbms_type) + { + case 'mysql': + $extractor = new mysql_extractor($download, $store, $format, $filename, $time); + break; + + case 'sqlite': + $extractor = new sqlite_extractor($download, $store, $format, $filename, $time); + break; + + case 'postgres': + $extractor = new postgres_extractor($download, $store, $format, $filename, $time); + break; + + case 'oracle': + $extractor = new oracle_extractor($download, $store, $format, $filename, $time); + break; + + case 'mssql': + $extractor = new mssql_extractor($download, $store, $format, $filename, $time); + break; + + case 'firebird': + $extractor = new firebird_extractor($download, $store, $format, $filename, $time); + break; + + case 'db2': + $extractor = new db2_extractor($download, $store, $format, $filename, $time); + break; + } + + $extractor->write_start($table_prefix); + + foreach ($table as $table_name) + { + // Get the table structure + if ($structure) + { + $extractor->write_table($table_name); + } + else + { + // We might wanna empty out all that junk :D + switch ($db->dbms_type) + { + case 'sqlite': + case 'firebird': + case 'db2': + $extractor->flush('DELETE FROM ' . $table_name . ";\n"); + break; + + case 'mssql': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "GO\n"); + break; + + case 'oracle': + $extractor->flush('TRUNCATE TABLE ' . $table_name . "\\\n"); + break; + + default: + $extractor->flush('TRUNCATE TABLE ' . $table_name . ";\n"); + break; + } + } + + // Data + if ($schema_data) + { + $extractor->write_data($table_name); + } + } + + $extractor->write_end(); + + add_log('admin', 'LOG_DB_BACKUP'); + + if ($download == true) + { + exit; + } + + trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action)); + break; + + default: + include(PHPBB_ROOT_PATH . 'includes/functions_install.' . PHP_EXT); + $tables = get_tables($db); + asort($tables); + foreach ($tables as $table_name) + { + if (strlen($table_prefix) === 0 || stripos($table_name, $table_prefix) === 0) + { + $template->assign_block_vars('tables', array( + 'TABLE' => $table_name + )); + } + } + unset($tables); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=download' + )); + + $available_methods = array('gzip' => 'zlib', 'bzip2' => 'bz2'); + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + + $template->assign_block_vars('methods', array( + 'TYPE' => $type + )); + } + + $template->assign_block_vars('methods', array( + 'TYPE' => 'text' + )); + break; + } + break; + + case 'restore': + + $this->page_title = 'ACP_RESTORE'; + + switch ($action) + { + case 'submit': + $delete = request_var('delete', ''); + $file = request_var('file', ''); + + if (!preg_match('#^backup_\d{10,}_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + { + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file_name = PHPBB_ROOT_PATH . 'store/' . $matches[0]; + + if (!file_exists($file_name) || !is_readable($file_name)) + { + trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($delete) + { + if (confirm_box(true)) + { + unlink($file_name); + add_log('admin', 'LOG_DB_DELETE'); + trigger_error($user->lang['BACKUP_DELETE'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['DELETE_SELECTED_BACKUP'], build_hidden_fields(array('delete' => $delete, 'file' => $file))); + } + } + else + { + $download = request_var('download', ''); + + if ($download) + { + $name = $matches[0]; + + switch ($matches[1]) + { + case 'sql': + $mimetype = 'text/x-sql'; + break; + case 'sql.bz2': + $mimetype = 'application/x-bzip2'; + break; + case 'sql.gz': + $mimetype = 'application/x-gzip'; + break; + } + + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"$name\""); + header("Content-disposition: attachment; filename=$name"); + + @set_time_limit(0); + + $fp = @fopen($file_name, 'rb'); + + if ($fp !== false) + { + while (!feof($fp)) + { + echo fread($fp, 8192); + } + fclose($fp); + } + + flush(); + exit; + } + + switch ($matches[1]) + { + case 'sql': + $fp = fopen($file_name, 'rb'); + $read = 'fread'; + $seek = 'fseek'; + $eof = 'feof'; + $close = 'fclose'; + $fgetd = 'fgetd'; + break; + + case 'sql.bz2': + $fp = bzopen($file_name, 'r'); + $read = 'bzread'; + $seek = ''; + $eof = 'feof'; + $close = 'bzclose'; + $fgetd = 'fgetd_seekless'; + break; + + case 'sql.gz': + $fp = gzopen($file_name, 'rb'); + $read = 'gzread'; + $seek = 'gzseek'; + $eof = 'gzeof'; + $close = 'gzclose'; + $fgetd = 'fgetd'; + break; + } + + switch ($db->dbms_type) + { + case 'mysql': + case 'sqlite': + case 'db2': + while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + + case 'firebird': + $delim = ";\n"; + while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) + { + $query = trim($sql); + if (substr($query, 0, 8) === 'SET TERM') + { + $delim = $query[9] . "\n"; + continue; + } + $db->sql_query($query); + } + break; + + case 'postgres': + $delim = ";\n"; + while (($sql = $fgetd($fp, $delim, $read, $seek, $eof)) !== false) + { + $query = trim($sql); + + if (substr($query, 0, 13) == 'CREATE DOMAIN') + { + list(, , $domain) = explode(' ', $query); + $sql = "SELECT domain_name + FROM information_schema.domains + WHERE domain_name = '$domain';"; + $result = $db->sql_query($sql); + if (!$db->sql_fetchrow($result)) + { + $db->sql_query($query); + } + $db->sql_freeresult($result); + } + else + { + $db->sql_query($query); + } + + if (substr($query, 0, 4) == 'COPY') + { + while (($sub = $fgetd($fp, "\n", $read, $seek, $eof)) !== '\.') + { + if ($sub === false) + { + trigger_error($user->lang['RESTORE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + pg_put_line($db->db_connect_id, $sub . "\n"); + } + pg_put_line($db->db_connect_id, "\\.\n"); + pg_end_copy($db->db_connect_id); + } + } + break; + + case 'oracle': + while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + + case 'mssql': + while (($sql = $fgetd($fp, "GO\n", $read, $seek, $eof)) !== false) + { + $db->sql_query($sql); + } + break; + } + + $close($fp); + + // Purge the cache due to updated data + $cache->purge(); + + add_log('admin', 'LOG_DB_RESTORE'); + trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action)); + break; + } + + default: + $methods = array('sql'); + $available_methods = array('sql.gz' => 'zlib', 'sql.bz2' => 'bz2'); + + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + $methods[] = $type; + } + + $dir = PHPBB_ROOT_PATH . 'store/'; + $dh = @opendir($dir); + + if ($dh) + { + while (($file = readdir($dh)) !== false) + { + if (preg_match('#^backup_(\d{10,})_[a-z\d]{16}\.(sql(?:\.(?:gz|bz2))?)$#', $file, $matches)) + { + $supported = in_array($matches[2], $methods); + + if ($supported == 'true') + { + $template->assign_block_vars('files', array( + 'FILE' => $file, + 'NAME' => gmdate("d-m-Y H:i:s", $matches[1]), + 'SUPPORTED' => $supported + )); + } + } + } + closedir($dh); + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action . '&action=submit' + )); + break; + } + break; + } + } +} + +/** +* @package acp +*/ +class base_extractor +{ + var $fh; + var $fp; + var $write; + var $close; + var $store; + var $download; + var $time; + var $format; + var $run_comp = false; + + function __construct($download = false, $store = false, $format, $filename, $time) + { + $this->download = $download; + $this->store = $store; + $this->time = $time; + $this->format = $format; + + switch ($format) + { + case 'text': + $ext = '.sql'; + $open = 'fopen'; + $this->write = 'fwrite'; + $this->close = 'fclose'; + $mimetype = 'text/x-sql'; + break; + case 'bzip2': + $ext = '.sql.bz2'; + $open = 'bzopen'; + $this->write = 'bzwrite'; + $this->close = 'bzclose'; + $mimetype = 'application/x-bzip2'; + break; + case 'gzip': + $ext = '.sql.gz'; + $open = 'gzopen'; + $this->write = 'gzwrite'; + $this->close = 'gzclose'; + $mimetype = 'application/x-gzip'; + break; + } + + if ($download == true) + { + $name = $filename . $ext; + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"$name\""); + header("Content-disposition: attachment; filename=$name"); + + switch ($format) + { + case 'bzip2': + ob_start(); + break; + + case 'gzip': + if ((isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), 'msie') === false) + { + ob_start('ob_gzhandler'); + } + else + { + $this->run_comp = true; + } + break; + } + } + + if ($store == true) + { + $file = PHPBB_ROOT_PATH . 'store/' . $filename . $ext; + + $this->fp = $open($file, 'w'); + + if (!$this->fp) + { + trigger_error('Unable to write temporary file to storage folder', E_USER_ERROR); + } + } + } + + function write_end() + { + static $close; + if ($this->store) + { + if ($close === null) + { + $close = $this->close; + } + $close($this->fp); + } + + // bzip2 must be written all the way at the end + if ($this->download && $this->format === 'bzip2') + { + $c = ob_get_clean(); + echo bzcompress($c); + } + } + + function flush($data) + { + static $write; + if ($this->store === true) + { + if ($write === null) + { + $write = $this->write; + } + $write($this->fp, $data); + } + + if ($this->download === true) + { + if ($this->format === 'bzip2' || $this->format === 'text' || ($this->format === 'gzip' && !$this->run_comp)) + { + echo $data; + } + + // we can write the gzip data as soon as we get it + if ($this->format === 'gzip') + { + if ($this->run_comp) + { + echo gzencode($data); + } + else + { + ob_flush(); + flush(); + } + } + } + } +} + +/** +* @package acp +*/ +class mysql_extractor extends base_extractor +{ + function write_start($table_prefix) + { + $sql_data = "#\n"; + $sql_data .= "# phpBB Backup Script\n"; + $sql_data .= "# Dump of tables for $table_prefix\n"; + $sql_data .= "# DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "#\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + + $sql = 'SHOW CREATE TABLE ' . $table_name; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + $sql_data = '# Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE IF EXISTS $table_name;\n"; + $this->flush($sql_data . $row['Create Table'] . ";\n\n"); + + $db->sql_freeresult($result); + } + + function write_data($table_name) + { + global $db; + if ($db->sql_layer === 'mysqli') + { + $this->write_data_mysqli($table_name); + } + else + { + $this->write_data_mysql($table_name); + } + } + + function write_data_mysqli($table_name) + { + global $db; + $sql = "SELECT * + FROM $table_name"; + $result = mysqli_query($db->db_connect_id, $sql, MYSQLI_USE_RESULT); + if ($result != false) + { + $fields_cnt = mysqli_num_fields($result); + + // Get field information + $field = mysqli_fetch_fields($result); + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysqli_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if (($field[$j]->flags & 32768) && !($field[$j]->flags & 1024)) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysqli_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } + + function write_data_mysql($table_name) + { + global $db; + $sql = "SELECT * + FROM $table_name"; + $result = mysql_unbuffered_query($sql, $db->db_connect_id); + + if ($result != false) + { + $fields_cnt = mysql_num_fields($result); + + // Get field information + $field = array(); + for ($i = 0; $i < $fields_cnt; $i++) + { + $field[] = mysql_fetch_field($result, $i); + } + $field_set = array(); + + for ($j = 0; $j < $fields_cnt; $j++) + { + $field_set[] = $field[$j]->name; + } + + $search = array("\\", "'", "\x00", "\x0a", "\x0d", "\x1a", '"'); + $replace = array("\\\\", "\\'", '\0', '\n', '\r', '\Z', '\\"'); + $fields = implode(', ', $field_set); + $sql_data = 'INSERT INTO ' . $table_name . ' (' . $fields . ') VALUES '; + $first_set = true; + $query_len = 0; + $max_len = get_usable_memory(); + + while ($row = mysql_fetch_row($result)) + { + $values = array(); + if ($first_set) + { + $query = $sql_data . '('; + } + else + { + $query .= ',('; + } + + for ($j = 0; $j < $fields_cnt; $j++) + { + if (!isset($row[$j]) || is_null($row[$j])) + { + $values[$j] = 'NULL'; + } + else if ($field[$j]->numeric && ($field[$j]->type !== 'timestamp')) + { + $values[$j] = $row[$j]; + } + else + { + $values[$j] = "'" . str_replace($search, $replace, $row[$j]) . "'"; + } + } + $query .= implode(', ', $values) . ')'; + + $query_len += strlen($query); + if ($query_len > $max_len) + { + $this->flush($query . ";\n\n"); + $query = ''; + $query_len = 0; + $first_set = true; + } + else + { + $first_set = false; + } + } + mysql_free_result($result); + + // check to make sure we have nothing left to flush + if (!$first_set && $query) + { + $this->flush($query . ";\n\n"); + } + } + } +} + +/** +* @package acp +*/ +class sqlite_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $db->sql_escape($table_name) . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create Table + $sql_data .= $row['sql'] . ";\n"; + + $result = $db->sql_query("PRAGMA index_list('" . $db->sql_escape($table_name) . "');"); + + $ar = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ar[] = $row; + } + $db->sql_freeresult($result); + + foreach ($ar as $value) + { + if (strpos($value['name'], 'autoindex') !== false) + { + continue; + } + + $result = $db->sql_query("PRAGMA index_info('" . $db->sql_escape($value['name']) . "');"); + + $fields = array(); + while ($row = $db->sql_fetchrow($result)) + { + $fields[] = $row['name']; + } + $db->sql_freeresult($result); + + $sql_data .= 'CREATE ' . ($value['unique'] ? 'UNIQUE ' : '') . 'INDEX ' . $value['name'] . ' on ' . $table_name . ' (' . implode(', ', $fields) . ");\n"; + } + + $this->flush($sql_data . "\n"); + } + + function write_data($table_name) + { + global $db; + static $proper; + + if (is_null($proper)) + { + $proper = version_compare(PHP_VERSION, '5.1.3', '>='); + } + + if ($proper) + { + $col_types = sqlite_fetch_column_types($db->db_connect_id, $table_name); + } + else + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . $table_name . "'"; + $table_data = sqlite_single_query($db->db_connect_id, $sql); + $table_data = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', '', $table_data); + $table_data = trim($table_data); + + preg_match('#\((.*)\)#s', $table_data, $matches); + + $table_cols = explode(',', trim($matches[1])); + foreach ($table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + $column_name = preg_replace('/"?([^"]+)"?/', '\1', $entities[0]); + + // Hit a primary key, those are not what we need :D + if (empty($entities[1]) || (strtolower($entities[0]) === 'primary' && strtolower($entities[1]) === 'key')) + { + continue; + } + $col_types[$column_name] = $entities[1]; + } + } + + $sql = "SELECT * + FROM $table_name"; + $result = sqlite_unbuffered_query($db->db_connect_id, $sql); + $rows = sqlite_fetch_all($result, SQLITE_ASSOC); + $sql_insert = 'INSERT INTO ' . $table_name . ' (' . implode(', ', array_keys($col_types)) . ') VALUES ('; + foreach ($rows as $row) + { + foreach ($row as $column_name => $column_data) + { + if (is_null($column_data)) + { + $row[$column_name] = 'NULL'; + } + else if ($column_data == '') + { + $row[$column_name] = "''"; + } + else if (strpos($col_types[$column_name], 'text') !== false || strpos($col_types[$column_name], 'char') !== false || strpos($col_types[$column_name], 'blob') !== false) + { + $row[$column_name] = sanitize_data_generic(str_replace("'", "''", $column_data)); + } + } + $this->flush($sql_insert . implode(', ', $row) . ");\n"); + } + } + + function write_end() + { + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} + +/** +* @package acp +*/ +class postgres_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION;\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + static $domains_created = array(); + + $sql = "SELECT a.domain_name, a.data_type, a.character_maximum_length, a.domain_default + FROM INFORMATION_SCHEMA.domains a, INFORMATION_SCHEMA.column_domain_usage b + WHERE a.domain_name = b.domain_name + AND b.table_name = '{$table_name}'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if (empty($domains_created[$row['domain_name']])) + { + $domains_created[$row['domain_name']] = true; + //$sql_data = "DROP DOMAIN {$row['domain_name']};\n"; + $sql_data = "CREATE DOMAIN {$row['domain_name']} as {$row['data_type']}"; + if (!empty($row['character_maximum_length'])) + { + $sql_data .= '(' . $row['character_maximum_length'] . ')'; + } + $sql_data .= ' NOT NULL'; + if (!empty($row['domain_default'])) + { + $sql_data .= ' DEFAULT ' . $row['domain_default']; + } + $this->flush($sql_data . ";\n"); + } + } + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + // PGSQL does not "tightly" bind sequences and tables, we must guess... + $sql = "SELECT relname + FROM pg_class + WHERE relkind = 'S' + AND relname = '{$table_name}_seq'"; + $result = $db->sql_query($sql); + // We don't even care about storing the results. We already know the answer if we get rows back. + if ($db->sql_fetchrow($result)) + { + $sql_data .= "DROP SEQUENCE {$table_name}_seq;\n"; + $sql_data .= "CREATE SEQUENCE {$table_name}_seq;\n"; + } + $db->sql_freeresult($result); + + $field_query = "SELECT a.attnum, a.attname as field, t.typname as type, a.attlen as length, a.atttypmod as lengthvar, a.attnotnull as notnull + FROM pg_class c, pg_attribute a, pg_type t + WHERE c.relname = '" . $db->sql_escape($table_name) . "' + AND a.attnum > 0 + AND a.attrelid = c.oid + AND a.atttypid = t.oid + ORDER BY a.attnum"; + $result = $db->sql_query($field_query); + + $sql_data .= "CREATE TABLE $table_name(\n"; + $lines = array(); + while ($row = $db->sql_fetchrow($result)) + { + // Get the data from the table + $sql_get_default = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '" . $db->sql_escape($table_name) . "') + AND (c.oid = d.adrelid) + AND d.adnum = " . $row['attnum']; + $def_res = $db->sql_query($sql_get_default); + + if (!$def_res) + { + unset($row['rowdefault']); + } + else + { + $row['rowdefault'] = $db->sql_fetchfield('rowdefault', $def_res); + } + $db->sql_freeresult($def_res); + + if ($row['type'] == 'bpchar') + { + // Internally stored as bpchar, but isn't accepted in a CREATE TABLE statement. + $row['type'] = 'char'; + } + + $line = ' ' . $row['field'] . ' ' . $row['type']; + + if (strpos($row['type'], 'char') !== false) + { + if ($row['lengthvar'] > 0) + { + $line .= '(' . ($row['lengthvar'] - 4) . ')'; + } + } + + if (strpos($row['type'], 'numeric') !== false) + { + $line .= '('; + $line .= sprintf("%s,%s", (($row['lengthvar'] >> 16) & 0xffff), (($row['lengthvar'] - 4) & 0xffff)); + $line .= ')'; + } + + if (isset($row['rowdefault'])) + { + $line .= ' DEFAULT ' . $row['rowdefault']; + } + + if ($row['notnull'] == 't') + { + $line .= ' NOT NULL'; + } + + $lines[] = $line; + } + $db->sql_freeresult($result); + + + // Get the listing of primary keys. + $sql_pri_keys = "SELECT ic.relname as index_name, bc.relname as tab_name, ta.attname as column_name, i.indisunique as unique_key, i.indisprimary as primary_key + FROM pg_class bc, pg_class ic, pg_index i, pg_attribute ta, pg_attribute ia + WHERE (bc.oid = i.indrelid) + AND (ic.oid = i.indexrelid) + AND (ia.attrelid = i.indexrelid) + AND (ta.attrelid = bc.oid) + AND (bc.relname = '" . $db->sql_escape($table_name) . "') + AND (ta.attrelid = i.indrelid) + AND (ta.attnum = i.indkey[ia.attnum-1]) + ORDER BY index_name, tab_name, column_name"; + + $result = $db->sql_query($sql_pri_keys); + + $index_create = $index_rows = $primary_key = array(); + + // We do this in two steps. It makes placing the comma easier + while ($row = $db->sql_fetchrow($result)) + { + if ($row['primary_key'] == 't') + { + $primary_key[] = $row['column_name']; + $primary_key_name = $row['index_name']; + } + else + { + // We have to store this all this info because it is possible to have a multi-column key... + // we can loop through it again and build the statement + $index_rows[$row['index_name']]['table'] = $table_name; + $index_rows[$row['index_name']]['unique'] = ($row['unique_key'] == 't') ? true : false; + $index_rows[$row['index_name']]['column_names'][] = $row['column_name']; + } + } + $db->sql_freeresult($result); + + if (!empty($index_rows)) + { + foreach ($index_rows as $idx_name => $props) + { + $index_create[] = 'CREATE ' . ($props['unique'] ? 'UNIQUE ' : '') . "INDEX $idx_name ON $table_name (" . implode(', ', $props['column_names']) . ");"; + } + } + + if (!empty($primary_key)) + { + $lines[] = " CONSTRAINT $primary_key_name PRIMARY KEY (" . implode(', ', $primary_key) . ")"; + } + + // Generate constraint clauses for CHECK constraints + $sql_checks = "SELECT conname as index_name, consrc + FROM pg_constraint, pg_class bc + WHERE conrelid = bc.oid + AND bc.relname = '" . $db->sql_escape($table_name) . "' + AND NOT EXISTS ( + SELECT * + FROM pg_constraint as c, pg_inherits as i + WHERE i.inhrelid = pg_constraint.conrelid + AND c.conname = pg_constraint.conname + AND c.consrc = pg_constraint.consrc + AND c.conrelid = i.inhparent + )"; + $result = $db->sql_query($sql_checks); + + // Add the constraints to the sql file. + while ($row = $db->sql_fetchrow($result)) + { + if (!is_null($row['consrc'])) + { + $lines[] = ' CONSTRAINT ' . $row['index_name'] . ' CHECK ' . $row['consrc']; + } + } + $db->sql_freeresult($result); + + $sql_data .= implode(", \n", $lines); + $sql_data .= "\n);\n"; + + if (!empty($index_create)) + { + $sql_data .= implode("\n", $index_create) . "\n\n"; + } + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = pg_num_fields($result); + $seq = ''; + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[] = pg_field_type($result, $i); + $ary_name[] = pg_field_name($result, $i); + + + $sql = "SELECT pg_get_expr(d.adbin, d.adrelid) as rowdefault + FROM pg_attrdef d, pg_class c + WHERE (c.relname = '{$table_name}') + AND (c.oid = d.adrelid) + AND d.adnum = " . strval($i + 1); + $result2 = $db->sql_query($sql); + if ($row = $db->sql_fetchrow($result2)) + { + // Determine if we must reset the sequences + if (strpos($row['rowdefault'], "nextval('") === 0) + { + $seq .= "SELECT SETVAL('{$table_name}_seq',(select case when max({$ary_name[$i]})>0 then max({$ary_name[$i]})+1 else 1 end FROM {$table_name}));\n"; + } + } + } + + $this->flush("COPY $table_name (" . implode(', ', $ary_name) . ') FROM stdin;' . "\n"); + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|bytea#i', $ary_type[$i])) + { + $str_val = str_replace(array("\n", "\t", "\r", "\b", "\f", "\v"), array('\n', '\t', '\r', '\b', '\f', '\v'), addslashes($str_val)); + $str_empty = ''; + } + else + { + $str_empty = '\N'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[] = $str_val; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $this->flush(implode("\t", $schema_vals) . "\n"); + } + $db->sql_freeresult($result); + $this->flush("\\.\n"); + + // Write out the sequence statements + $this->flush($seq); + } + + function write_end() + { + $this->flush("COMMIT;\n"); + parent::write_end(); + } +} + +/** +* @package acp +*/ +class mssql_extractor extends base_extractor +{ + function write_end() + { + $this->flush("COMMIT\nGO\n"); + parent::write_end(); + } + + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $sql_data .= "BEGIN TRANSACTION\n"; + $sql_data .= "GO\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "IF OBJECT_ID(N'$table_name', N'U') IS NOT NULL\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= "GO\n"; + $sql_data .= "\nCREATE TABLE [$table_name] (\n"; + $rows = array(); + + $text_flag = false; + + $sql = "SELECT COLUMN_NAME, COLUMN_DEFAULT, IS_NULLABLE, DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME, 'IsIdentity') as IS_IDENTITY + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_NAME = '$table_name'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $line = "\t[{$row['COLUMN_NAME']}] [{$row['DATA_TYPE']}]"; + + if ($row['DATA_TYPE'] == 'text') + { + $text_flag = true; + } + + if ($row['IS_IDENTITY']) + { + $line .= ' IDENTITY (1 , 1)'; + } + + if ($row['CHARACTER_MAXIMUM_LENGTH'] && $row['DATA_TYPE'] !== 'text') + { + $line .= ' (' . $row['CHARACTER_MAXIMUM_LENGTH'] . ')'; + } + + if ($row['IS_NULLABLE'] == 'YES') + { + $line .= ' NULL'; + } + else + { + $line .= ' NOT NULL'; + } + + if ($row['COLUMN_DEFAULT']) + { + $line .= ' DEFAULT ' . $row['COLUMN_DEFAULT']; + } + + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n) ON [PRIMARY]"; + + if ($text_flag) + { + $sql_data .= " TEXTIMAGE_ON [PRIMARY]"; + } + + $sql_data .= "\nGO\n\n"; + $rows = array(); + + $sql = "SELECT CONSTRAINT_NAME, COLUMN_NAME + FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE + WHERE TABLE_NAME = '$table_name'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if (!sizeof($rows)) + { + $sql_data .= "ALTER TABLE [$table_name] WITH NOCHECK ADD\n"; + $sql_data .= "\tCONSTRAINT [{$row['CONSTRAINT_NAME']}] PRIMARY KEY CLUSTERED \n\t(\n"; + } + $rows[] = "\t\t[{$row['COLUMN_NAME']}]"; + } + if (sizeof($rows)) + { + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n\t) ON [PRIMARY] \nGO\n"; + } + $db->sql_freeresult($result); + + $index = array(); + $sql = "EXEC sp_statistics '$table_name'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['TYPE'] == 3) + { + $index[$row['INDEX_NAME']][] = '[' . $row['COLUMN_NAME'] . ']'; + } + } + $db->sql_freeresult($result); + + foreach ($index as $index_name => $column_name) + { + $index[$index_name] = implode(', ', $column_name); + } + + foreach ($index as $index_name => $columns) + { + $sql_data .= "\nCREATE INDEX [$index_name] ON [$table_name]($columns) ON [PRIMARY]\nGO\n"; + } + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + + if ($db->sql_layer === 'mssql') + { + $this->write_data_mssql($table_name); + } + else if ($db->sql_layer === 'mssql_odbc') + { + $this->write_data_odbc($table_name); + } + else + { + // @todo: write code for MS SQL 2005 DBAL + trigger_error('KungFuDeathGrip'); + } + } + + function write_data_mssql($table_name) + { + global $db; + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $retrieved_data = mssql_num_rows($result); + + $i_num_fields = mssql_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = mssql_field_type($result, $i); + $ary_name[$i] = mssql_field_name($result, $i); + } + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $db->sql_freeresult($result2); + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + $sql_data = ''; + } + $db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + + function write_data_odbc($table_name) + { + global $db; + $ary_type = $ary_name = array(); + $ident_set = false; + $sql_data = ''; + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $retrieved_data = odbc_num_rows($result); + + if ($retrieved_data) + { + $sql = "SELECT 1 as has_identity + FROM INFORMATION_SCHEMA.COLUMNS + WHERE COLUMNPROPERTY(object_id('$table_name'), COLUMN_NAME, 'IsIdentity') = 1"; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + if (!empty($row2['has_identity'])) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name ON\nGO\n"; + $ident_set = true; + } + $db->sql_freeresult($result2); + } + + $i_num_fields = odbc_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = odbc_field_type($result, $i + 1); + $ary_name[$i] = odbc_field_name($result, $i + 1); + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|varbinary#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_mssql(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0' && !(is_int($str_val) || is_float($str_val))) + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = $ary_name[$i]; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data .= "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\nGO\n"; + + $this->flush($sql_data); + + $sql_data = ''; + + } + $db->sql_freeresult($result); + + if ($retrieved_data && $ident_set) + { + $sql_data .= "\nSET IDENTITY_INSERT $table_name OFF\nGO\n"; + } + $this->flush($sql_data); + } + +} + +/** +* @package acp +*/ +class db2_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } + + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "\nCREATE TABLE $table_name (\n"; + $rows = array(); + + // switch to db2_columns()? + $sql = "SELECT colname, typename, length, default, identity, nulls + FROM syscat.columns + WHERE tabname = '$table_name'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $line = "\t{$row['colname']} {$row['typename']}"; + + if ($row['identity'] == 'Y') + { + $line .= ' GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1)'; + } + + if ($row['typename'] == 'VARCHAR' || $row['typename'] == 'CHARACTER' || $row['typename'] == 'CLOB') + { + $line .= ' (' . $row['length'] . ')'; + } + + if ($row['nulls'] == 'N') + { + $line .= ' NOT NULL'; + } + else + { + $line .= ' NULL'; + } + + if ($row['default'] !== null) + { + $line .= ' DEFAULT ' . $row['default']; + } + + $rows[] = $line; + } + $db->sql_freeresult($result); + + // switch to db2_columns()? + $sql = "SELECT colname + FROM SYSCAT.KEYCOLUSE + WHERE tabname = '$table_name'"; + $result = $db->sql_query($sql); + $prim_cols = array(); + while ($row = $db->sql_fetchrow($result)) + { + $prim_cols[] = $row['colname']; + } + $db->sql_freeresult($result); + if (sizeof($prim_cols)) + { + $rows[] = "\tPRIMARY KEY (" . implode($prim_cols) . ')'; + } + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n);\n\n"; + $rows = array(); + + $sql = "SELECT colnames, indname + FROM SYSCAT.INDEXES + WHERE TABNAME = '$table_name' + AND UNIQUERULE <> 'P'"; + $result = $db->sql_query($sql); + $index = array(); + while ($row = $db->sql_fetchrow($result)) + { + $inds = explode('+', $row['colnames']); + unset($inds[0]); + $sql_data .= 'CREATE INDEX ' . $row['indname'] . ' ON ' . $table_name . ' (' . implode(', ', $inds) . ") PCTFREE 10 MINPCTUSED 10 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COLLECT SAMPLED DETAILED STATISTICS;\n"; + } + $db->sql_freeresult($result); + + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + $ary_type = $ary_name = array(); + $result = db2_columns($db->db_connect_id, '', '%', $table_name); + $i = 0; + while ($row = $db->sql_fetchrow($result)) + { + $ary_type[$i] = $row['type_name']; + $ary_name[$i++] = strtolower($row['column_name']); + } + $db->sql_freeresult($result); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $sql_data = ''; + $i_num_fields = $i; + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|clob#i', $ary_type[$i])) + { + $str_quote = "'"; + $str_empty = ''; + $str_val = sanitize_data_generic(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . "'"; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; + + $this->flush($sql_data); + } + $db->sql_freeresult($result); + } +} + +/** +* @package acp +*/ +class oracle_extractor extends base_extractor +{ + function write_table($table_name) + { + global $db; + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + $sql_data .= '\\' . "\n"; + $sql_data .= "\nCREATE TABLE $table_name (\n"; + + $sql = "SELECT COLUMN_NAME, DATA_TYPE, DATA_PRECISION, DATA_LENGTH, NULLABLE, DATA_DEFAULT + FROM ALL_TAB_COLS + WHERE table_name = '{$table_name}'"; + $result = $db->sql_query($sql); + + $rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $line = ' "' . $row['column_name'] . '" ' . $row['data_type']; + + if ($row['data_type'] !== 'CLOB') + { + if ($row['data_type'] !== 'VARCHAR2') + { + $line .= '(' . $row['data_precision'] . ')'; + } + else + { + $line .= '(' . $row['data_length'] . ')'; + } + } + + if (!empty($row['data_default'])) + { + $line .= ' DEFAULT ' . $row['data_default']; + } + + if ($row['nullable'] == 'N') + { + $line .= ' NOT NULL'; + } + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'P' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $rows[] = " CONSTRAINT {$row['constraint_name']} PRIMARY KEY ({$row['column_name']})"; + } + $db->sql_freeresult($result); + + $sql = "SELECT A.CONSTRAINT_NAME, A.COLUMN_NAME + FROM USER_CONS_COLUMNS A, USER_CONSTRAINTS B + WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME + AND B.CONSTRAINT_TYPE = 'U' + AND A.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $rows[] = " CONSTRAINT {$row['constraint_name']} UNIQUE ({$row['column_name']})"; + } + $db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n)\n\\"; + + $sql = "SELECT A.REFERENCED_NAME + FROM USER_DEPENDENCIES A, USER_TRIGGERS B + WHERE A.REFERENCED_TYPE = 'SEQUENCE' + AND A.NAME = B.TRIGGER_NAME + AND B.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $sql_data .= "\nCREATE SEQUENCE {$row['referenced_name']}\\\n"; + } + $db->sql_freeresult($result); + + $sql = "SELECT DESCRIPTION, WHEN_CLAUSE, TRIGGER_BODY + FROM USER_TRIGGERS + WHERE TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $sql_data .= "\nCREATE OR REPLACE TRIGGER {$row['description']}WHEN ({$row['when_clause']})\n{$row['trigger_body']}\\"; + } + $db->sql_freeresult($result); + + $sql = "SELECT A.INDEX_NAME, B.COLUMN_NAME + FROM USER_INDEXES A, USER_IND_COLUMNS B + WHERE A.UNIQUENESS = 'NONUNIQUE' + AND A.INDEX_NAME = B.INDEX_NAME + AND B.TABLE_NAME = '{$table_name}'"; + $result = $db->sql_query($sql); + + $index = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $index[$row['index_name']][] = $row['column_name']; + } + + foreach ($index as $index_name => $column_names) + { + $sql_data .= "\nCREATE INDEX $index_name ON $table_name(" . implode(', ', $column_names) . ")\n\\"; + } + $db->sql_freeresult($result); + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + $ary_type = $ary_name = array(); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = ocinumcols($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $ary_type[$i] = ocicolumntype($result, $i + 1); + $ary_name[$i] = ocicolumnname($result, $i + 1); + } + + $sql_data = ''; + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[$ary_name[$i]]; + + if (preg_match('#char|text|bool|raw#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_oracle($str_val); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . "'"; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; + + $this->flush($sql_data); + } + $db->sql_freeresult($result); + } + + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } +} + +/** +* @package acp +*/ +class firebird_extractor extends base_extractor +{ + function write_start($prefix) + { + $sql_data = "--\n"; + $sql_data .= "-- phpBB Backup Script\n"; + $sql_data .= "-- Dump of tables for $prefix\n"; + $sql_data .= "-- DATE : " . gmdate("d-m-Y H:i:s", $this->time) . " GMT\n"; + $sql_data .= "--\n"; + $this->flush($sql_data); + } + + function write_data($table_name) + { + global $db; + $ary_type = $ary_name = array(); + + // Grab all of the data from current table. + $sql = "SELECT * + FROM $table_name"; + $result = $db->sql_query($sql); + + $i_num_fields = ibase_num_fields($result); + + for ($i = 0; $i < $i_num_fields; $i++) + { + $info = ibase_field_info($result, $i); + $ary_type[$i] = $info['type']; + $ary_name[$i] = $info['name']; + } + + while ($row = $db->sql_fetchrow($result)) + { + $schema_vals = $schema_fields = array(); + + // Build the SQL statement to recreate the data. + for ($i = 0; $i < $i_num_fields; $i++) + { + $str_val = $row[strtolower($ary_name[$i])]; + + if (preg_match('#char|text|bool|varbinary|blob#i', $ary_type[$i])) + { + $str_quote = ''; + $str_empty = "''"; + $str_val = sanitize_data_generic(str_replace("'", "''", $str_val)); + } + else if (preg_match('#date|timestamp#i', $ary_type[$i])) + { + if (empty($str_val)) + { + $str_quote = ''; + } + else + { + $str_quote = "'"; + } + } + else + { + $str_quote = ''; + $str_empty = 'NULL'; + } + + if (empty($str_val) && $str_val !== '0') + { + $str_val = $str_empty; + } + + $schema_vals[$i] = $str_quote . $str_val . $str_quote; + $schema_fields[$i] = '"' . $ary_name[$i] . '"'; + } + + // Take the ordered fields and their associated data and build it + // into a valid sql statement to recreate that field in the data. + $sql_data = "INSERT INTO $table_name (" . implode(', ', $schema_fields) . ') VALUES (' . implode(', ', $schema_vals) . ");\n"; + + $this->flush($sql_data); + } + $db->sql_freeresult($result); + } + + function write_table($table_name) + { + global $db; + + $sql_data = '-- Table: ' . $table_name . "\n"; + $sql_data .= "DROP TABLE $table_name;\n"; + + $data_types = array(7 => 'SMALLINT', 8 => 'INTEGER', 10 => 'FLOAT', 12 => 'DATE', 13 => 'TIME', 14 => 'CHARACTER', 27 => 'DOUBLE PRECISION', 35 => 'TIMESTAMP', 37 => 'VARCHAR', 40 => 'CSTRING', 261 => 'BLOB', 701 => 'DECIMAL', 702 => 'NUMERIC'); + + $sql_data .= "\nCREATE TABLE $table_name (\n"; + + $sql = 'SELECT DISTINCT R.RDB$FIELD_NAME as FNAME, R.RDB$NULL_FLAG as NFLAG, R.RDB$DEFAULT_SOURCE as DSOURCE, F.RDB$FIELD_TYPE as FTYPE, F.RDB$FIELD_SUB_TYPE as STYPE, F.RDB$FIELD_LENGTH as FLEN + FROM RDB$RELATION_FIELDS R + JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME + LEFT JOIN RDB$FIELD_DIMENSIONS D ON R.RDB$FIELD_SOURCE = D.RDB$FIELD_NAME + WHERE F.RDB$SYSTEM_FLAG = 0 + AND R.RDB$RELATION_NAME = \''. $table_name . '\' + ORDER BY R.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + $rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $line = "\t" . '"' . $row['fname'] . '" ' . $data_types[$row['ftype']]; + + if ($row['ftype'] == 261 && $row['stype'] == 1) + { + $line .= ' SUB_TYPE TEXT'; + } + + if ($row['ftype'] == 37 || $row['ftype'] == 14) + { + $line .= ' (' . $row['flen'] . ')'; + } + + if (!empty($row['dsource'])) + { + $line .= ' ' . $row['dsource']; + } + + if (!empty($row['nflag'])) + { + $line .= ' NOT NULL'; + } + $rows[] = $line; + } + $db->sql_freeresult($result); + + $sql_data .= implode(",\n", $rows); + $sql_data .= "\n);\n"; + $keys = array(); + + $sql = 'SELECT I.RDB$FIELD_NAME as NAME + FROM RDB$RELATION_CONSTRAINTS RC, RDB$INDEX_SEGMENTS I, RDB$INDICES IDX + WHERE (I.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) + AND (IDX.RDB$INDEX_NAME = RC.RDB$INDEX_NAME) + AND (RC.RDB$RELATION_NAME = \''. $table_name . '\') + ORDER BY I.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $keys[] = $row['name']; + } + + if (sizeof($keys)) + { + $sql_data .= "\nALTER TABLE $table_name ADD PRIMARY KEY (" . implode(', ', $keys) . ');'; + } + + $db->sql_freeresult($result); + + $sql = 'SELECT I.RDB$INDEX_NAME as INAME, I.RDB$UNIQUE_FLAG as UFLAG, S.RDB$FIELD_NAME as FNAME + FROM RDB$INDICES I JOIN RDB$INDEX_SEGMENTS S ON S.RDB$INDEX_NAME=I.RDB$INDEX_NAME + WHERE (I.RDB$SYSTEM_FLAG IS NULL OR I.RDB$SYSTEM_FLAG=0) + AND I.RDB$FOREIGN_KEY IS NULL + AND I.RDB$RELATION_NAME = \''. $table_name . '\' + AND I.RDB$INDEX_NAME NOT STARTING WITH \'RDB$\' + ORDER BY S.RDB$FIELD_POSITION'; + $result = $db->sql_query($sql); + + $index = array(); + while ($row = $db->sql_fetchrow($result)) + { + $index[$row['iname']]['unique'] = !empty($row['uflag']); + $index[$row['iname']]['values'][] = $row['fname']; + } + + foreach ($index as $index_name => $data) + { + $sql_data .= "\nCREATE "; + if ($data['unique']) + { + $sql_data .= 'UNIQUE '; + } + $sql_data .= "INDEX $index_name ON $table_name(" . implode(', ', $data['values']) . ");"; + } + $sql_data .= "\n"; + + $db->sql_freeresult($result); + + $sql = 'SELECT D1.RDB$DEPENDENT_NAME as DNAME, D1.RDB$FIELD_NAME as FNAME, D1.RDB$DEPENDENT_TYPE, R1.RDB$RELATION_NAME + FROM RDB$DEPENDENCIES D1 + LEFT JOIN RDB$RELATIONS R1 ON ((D1.RDB$DEPENDENT_NAME = R1.RDB$RELATION_NAME) AND (NOT (R1.RDB$VIEW_BLR IS NULL))) + WHERE (D1.RDB$DEPENDED_ON_TYPE = 0) + AND (D1.RDB$DEPENDENT_TYPE <> 3) + AND (D1.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') + UNION SELECT DISTINCT F2.RDB$RELATION_NAME, D2.RDB$FIELD_NAME, D2.RDB$DEPENDENT_TYPE, R2.RDB$RELATION_NAME FROM RDB$DEPENDENCIES D2, RDB$RELATION_FIELDS F2 + LEFT JOIN RDB$RELATIONS R2 ON ((F2.RDB$RELATION_NAME = R2.RDB$RELATION_NAME) AND (NOT (R2.RDB$VIEW_BLR IS NULL))) + WHERE (D2.RDB$DEPENDENT_TYPE = 3) + AND (D2.RDB$DEPENDENT_NAME = F2.RDB$FIELD_SOURCE) + AND (D2.RDB$DEPENDED_ON_NAME = \'' . $table_name . '\') + ORDER BY 1, 2'; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $sql = 'SELECT T1.RDB$DEPENDED_ON_NAME as GEN, T1.RDB$FIELD_NAME, T1.RDB$DEPENDED_ON_TYPE + FROM RDB$DEPENDENCIES T1 + WHERE (T1.RDB$DEPENDENT_NAME = \'' . $row['dname'] . '\') + AND (T1.RDB$DEPENDENT_TYPE = 2 AND T1.RDB$DEPENDED_ON_TYPE = 14) + UNION ALL SELECT DISTINCT D.RDB$DEPENDED_ON_NAME, D.RDB$FIELD_NAME, D.RDB$DEPENDED_ON_TYPE + FROM RDB$DEPENDENCIES D, RDB$RELATION_FIELDS F + WHERE (D.RDB$DEPENDENT_TYPE = 3) + AND (D.RDB$DEPENDENT_NAME = F.RDB$FIELD_SOURCE) + AND (F.RDB$RELATION_NAME = \'' . $row['dname'] . '\') + ORDER BY 1,2'; + $result2 = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result2); + $db->sql_freeresult($result2); + $gen_name = $row2['gen']; + + $sql_data .= "\nDROP GENERATOR " . $gen_name . ";"; + $sql_data .= "\nSET TERM ^ ;"; + $sql_data .= "\nCREATE GENERATOR " . $gen_name . "^"; + $sql_data .= "\nSET GENERATOR " . $gen_name . " TO 0^\n"; + $sql_data .= "\nCREATE TRIGGER {$row['dname']} FOR $table_name"; + $sql_data .= "\nBEFORE INSERT\nAS\nBEGIN"; + $sql_data .= "\n NEW.{$row['fname']} = GEN_ID(" . $gen_name . ", 1);"; + $sql_data .= "\nEND^\n"; + $sql_data .= "\nSET TERM ; ^\n"; + } + + $this->flush($sql_data); + + $db->sql_freeresult($result); + } +} + +// get how much space we allow for a chunk of data, very similar to phpMyAdmin's way of doing things ;-) (hey, we only do this for MySQL anyway :P) +function get_usable_memory() +{ + $val = trim(@ini_get('memory_limit')); + + if (preg_match('/(\\d+)([mkg]?)/i', $val, $regs)) + { + $memory_limit = (int) $regs[1]; + switch ($regs[2]) + { + + case 'k': + case 'K': + $memory_limit *= 1024; + break; + + case 'm': + case 'M': + $memory_limit *= 1048576; + break; + + case 'g': + case 'G': + $memory_limit *= 1073741824; + break; + } + + // how much memory PHP requires at the start of export (it is really a little less) + if ($memory_limit > 6100000) + { + $memory_limit -= 6100000; + } + + // allow us to consume half of the total memory available + $memory_limit /= 2; + } + else + { + // set the buffer to 1M if we have no clue how much memory PHP will give us :P + $memory_limit = 1048576; + } + + return $memory_limit; +} + +function sanitize_data_mssql($text) +{ + $data = preg_split('/[\n\t\r\b\f]/', $text); + preg_match_all('/[\n\t\r\b\f]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = 'char(' . ord(array_shift($matches[0])) . ')'; + } + } + + return implode('+', $val); +} + +function sanitize_data_oracle($text) +{ + $data = preg_split('/[\0\n\t\r\b\f\'"\\\]/', $text); + preg_match_all('/[\0\n\t\r\b\f\'"\\\]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = 'chr(' . ord(array_shift($matches[0])) . ')'; + } + } + + return implode('||', $val); +} + +function sanitize_data_generic($text) +{ + $data = preg_split('/[\n\t\r\b\f]/', $text); + preg_match_all('/[\n\t\r\b\f]/', $text, $matches); + + $val = array(); + + foreach ($data as $value) + { + if (strlen($value)) + { + $val[] = "'" . $value . "'"; + } + if (sizeof($matches[0])) + { + $val[] = "'" . array_shift($matches[0]) . "'"; + } + } + + return implode('||', $val); +} + +// modified from PHP.net +function fgetd(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) +{ + $record = ''; + $delim_len = strlen($delim); + + while (!$eof($fp)) + { + $pos = strpos($record, $delim); + if ($pos === false) + { + $record .= $read($fp, $buffer); + if ($eof($fp) && ($pos = strpos($record, $delim)) !== false) + { + $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); + return substr($record, 0, $pos); + } + } + else + { + $seek($fp, $pos + $delim_len - strlen($record), SEEK_CUR); + return substr($record, 0, $pos); + } + } + + return false; +} + +function fgetd_seekless(&$fp, $delim, $read, $seek, $eof, $buffer = 8192) +{ + static $array = array(); + static $record = ''; + + if (!sizeof($array)) + { + while (!$eof($fp)) + { + if (strpos($record, $delim) !== false) + { + $array = explode($delim, $record); + $record = array_pop($array); + break; + } + else + { + $record .= $read($fp, $buffer); + } + } + if ($eof($fp) && strpos($record, $delim) !== false) + { + $array = explode($delim, $record); + $record = array_pop($array); + } + } + + if (sizeof($array)) + { + return array_shift($array); + } + + return false; +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_disallow.php b/phpBB/modules/acp/acp_disallow.php new file mode 100644 index 0000000000..ec124b043f --- /dev/null +++ b/phpBB/modules/acp/acp_disallow.php @@ -0,0 +1,107 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_disallow +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $user->add_lang('acp/posting'); + + // Set up general vars + $this->tpl_name = 'acp_disallow'; + $this->page_title = 'ACP_DISALLOW_USERNAMES'; + + $form_key = 'acp_disallow'; + add_form_key($form_key); + + $disallow = request::is_set_post('disallow'); + $allow = request::is_set_post('allow'); + + if (($allow || $disallow) && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($disallow) + { + $disallowed_user = str_replace('*', '%', utf8_normalize_nfc(request_var('disallowed_user', '', true))); + + if (!$disallowed_user) + { + trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'INSERT INTO ' . DISALLOW_TABLE . ' ' . $db->sql_build_array('INSERT', array('disallow_username' => $disallowed_user)); + $db->sql_query($sql); + + $cache->destroy('_disallowed_usernames'); + + $message = $user->lang['DISALLOW_SUCCESSFUL']; + add_log('admin', 'LOG_DISALLOW_ADD', str_replace('%', '*', $disallowed_user)); + + trigger_error($message . adm_back_link($this->u_action)); + } + else if ($allow) + { + $disallowed_id = request_var('disallowed_id', 0); + + if (!$disallowed_id) + { + trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'DELETE FROM ' . DISALLOW_TABLE . ' + WHERE disallow_id = ' . $disallowed_id; + $db->sql_query($sql); + + $cache->destroy('_disallowed_usernames'); + + add_log('admin', 'LOG_DISALLOW_DELETE'); + + trigger_error($user->lang['DISALLOWED_DELETED'] . adm_back_link($this->u_action)); + } + + // Grab the current list of disallowed usernames... + $sql = 'SELECT * + FROM ' . DISALLOW_TABLE; + $result = $db->sql_query($sql); + + $disallow_select = ''; + while ($row = $db->sql_fetchrow($result)) + { + $disallow_select .= '<option value="' . $row['disallow_id'] . '">' . str_replace('%', '*', $row['disallow_username']) . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_DISALLOWED_NAMES' => $disallow_select) + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_email.php b/phpBB/modules/acp/acp_email.php new file mode 100644 index 0000000000..1e39049eca --- /dev/null +++ b/phpBB/modules/acp/acp_email.php @@ -0,0 +1,260 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_email +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + $user->add_lang('acp/email'); + $this->tpl_name = 'acp_email'; + $this->page_title = 'ACP_MASS_EMAIL'; + + $form_key = 'acp_email'; + add_form_key($form_key); + + // Set some vars + $submit = request::is_set_post('submit'); + $error = array(); + + $usernames = request_var('usernames', '', true); + $group_id = request_var('g', 0); + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $message = utf8_normalize_nfc(request_var('message', '', true)); + + // Do the job ... + if ($submit) + { + // Error checking needs to go here ... if no subject and/or no message then skip + // over the send and return to the form + $use_queue = request::is_set_post('send_immediately'); + $priority = request_var('mail_priority_flag', MAIL_NORMAL_PRIORITY); + + if (!check_form_key($form_key)) + { + $error[] = $user->lang['FORM_INVALID']; + } + + if (!$subject) + { + $error[] = $user->lang['NO_EMAIL_SUBJECT']; + } + + if (!$message) + { + $error[] = $user->lang['NO_EMAIL_MESSAGE']; + } + + if (!sizeof($error)) + { + if ($usernames) + { + // If giving usernames the admin is able to email inactive users too... + $sql = 'SELECT username, user_email, user_jabber, user_notify_type, user_lang + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', explode("\n", $usernames))) . ' + AND user_allow_massemail = 1 + ORDER BY user_lang, user_notify_type'; // , SUBSTRING(user_email FROM INSTR(user_email, '@')) + } + else + { + if ($group_id) + { + $sql = 'SELECT u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug + WHERE ug.group_id = ' . $group_id . ' + AND ug.user_pending = 0 + AND u.user_id = ug.user_id + AND u.user_allow_massemail = 1 + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') + ORDER BY u.user_lang, u.user_notify_type'; + } + else + { + $sql = 'SELECT username, username_clean, user_email, user_jabber, user_notify_type, user_lang + FROM ' . USERS_TABLE . ' + WHERE user_allow_massemail = 1 + AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ') + ORDER BY user_lang, user_notify_type'; + } + } + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + if (!$row) + { + $db->sql_freeresult($result); + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $i = $j = 0; + + // Send with BCC, no more than 50 recipients for one mail (to not exceed the limit) + $max_chunk_size = 50; + $email_list = array(); + $old_lang = $row['user_lang']; + $old_notify_type = $row['user_notify_type']; + + do + { + if (($row['user_notify_type'] == NOTIFY_EMAIL && $row['user_email']) || + ($row['user_notify_type'] == NOTIFY_IM && $row['user_jabber']) || + ($row['user_notify_type'] == NOTIFY_BOTH && $row['user_email'] && $row['user_jabber'])) + { + if ($i == $max_chunk_size || $row['user_lang'] != $old_lang || $row['user_notify_type'] != $old_notify_type) + { + $i = 0; + + if (sizeof($email_list)) + { + $j++; + } + + $old_lang = $row['user_lang']; + $old_notify_type = $row['user_notify_type']; + } + + $email_list[$j][$i]['lang'] = $row['user_lang']; + $email_list[$j][$i]['method'] = $row['user_notify_type']; + $email_list[$j][$i]['email'] = $row['user_email']; + $email_list[$j][$i]['name'] = $row['username']; + $email_list[$j][$i]['jabber'] = $row['user_jabber']; + $i++; + } + } + while ($row = $db->sql_fetchrow($result)); + $db->sql_freeresult($result); + + // Send the messages + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + $messenger = new messenger($use_queue); + + $errored = false; + + for ($i = 0, $size = sizeof($email_list); $i < $size; $i++) + { + $used_lang = $email_list[$i][0]['lang']; + $used_method = $email_list[$i][0]['method']; + + for ($j = 0, $list_size = sizeof($email_list[$i]); $j < $list_size; $j++) + { + $email_row = $email_list[$i][$j]; + + $messenger->{((sizeof($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']); + $messenger->im($email_row['jabber'], $email_row['name']); + } + + $messenger->template('admin_send_email', $used_lang); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->subject(htmlspecialchars_decode($subject)); + $messenger->set_mail_priority($priority); + + $messenger->assign_vars(array( + 'CONTACT_EMAIL' => $config['board_contact'], + 'MESSAGE' => htmlspecialchars_decode($message)) + ); + + if (!($messenger->send($used_method))) + { + $errored = true; + } + } + unset($email_list); + + $messenger->save_queue(); + + if ($usernames) + { + $usernames = explode("\n", $usernames); + add_log('admin', 'LOG_MASS_EMAIL', implode(', ', utf8_normalize_nfc($usernames))); + } + else + { + if ($group_id) + { + $group_name = get_group_name($group_id); + } + else + { + // Not great but the logging routine doesn't cope well with localising on the fly + $group_name = $user->lang['ALL_USERS']; + } + + add_log('admin', 'LOG_MASS_EMAIL', $group_name); + } + + if (!$errored) + { + $message = ($use_queue) ? $user->lang['EMAIL_SENT_QUEUE'] : $user->lang['EMAIL_SENT']; + trigger_error($message . adm_back_link($this->u_action)); + } + else + { + $message = sprintf($user->lang['EMAIL_SEND_ERROR'], '<a href="' . append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=logs&mode=critical') . '">', '</a>'); + trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + + // Exclude bots and guests... + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name_clean IN ('bots', 'guests')"; + $result = $db->sql_query($sql); + + $exclude = array(); + while ($row = $db->sql_fetchrow($result)) + { + $exclude[] = $row['group_id']; + } + $db->sql_freeresult($result); + + $select_list = '<option value="0"' . ((!$group_id) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_USERS'] . '</option>'; + $select_list .= group_select_options($group_id, $exclude); + + $s_priority_options = '<option value="' . MAIL_LOW_PRIORITY . '">' . $user->lang['MAIL_LOW_PRIORITY'] . '</option>'; + $s_priority_options .= '<option value="' . MAIL_NORMAL_PRIORITY . '" selected="selected">' . $user->lang['MAIL_NORMAL_PRIORITY'] . '</option>'; + $s_priority_options .= '<option value="' . MAIL_HIGH_PRIORITY . '">' . $user->lang['MAIL_HIGH_PRIORITY'] . '</option>'; + + $template->assign_vars(array( + 'S_WARNING' => (sizeof($error)) ? true : false, + 'WARNING_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'U_ACTION' => $this->u_action, + 'S_GROUP_OPTIONS' => $select_list, + 'USERNAMES' => $usernames, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=acp_email&field=usernames'), + 'SUBJECT' => $subject, + 'MESSAGE' => $message, + 'S_PRIORITY_OPTIONS' => $s_priority_options, + )); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_forums.php b/phpBB/modules/acp/acp_forums.php new file mode 100644 index 0000000000..37453f2f34 --- /dev/null +++ b/phpBB/modules/acp/acp_forums.php @@ -0,0 +1,1931 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_forums +{ + var $u_action; + var $parent_id = 0; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('acp/forums'); + $this->tpl_name = 'acp_forums'; + $this->page_title = 'ACP_MANAGE_FORUMS'; + + $form_key = 'acp_forums'; + add_form_key($form_key); + + $action = request_var('action', ''); + $update = request::is_set_post('update'); + $forum_id = request_var('f', 0); + + $this->parent_id = request_var('parent_id', 0); + $forum_data = $errors = array(); + if ($update && !check_form_key($form_key)) + { + $update = false; + $errors[] = $user->lang['FORM_INVALID']; + } + + // Check additional permissions + switch ($action) + { + case 'progress_bar': + $start = request_var('start', 0); + $total = request_var('total', 0); + + $this->display_progress_bar($start, $total); + exit; + break; + + case 'delete': + + if (!$auth->acl_get('a_forumdel')) + { + trigger_error($user->lang['NO_PERMISSION_FORUM_DELETE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + break; + + case 'add': + + if (!$auth->acl_get('a_forumadd')) + { + trigger_error($user->lang['NO_PERMISSION_FORUM_ADD'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + break; + } + + // Major routines + if ($update) + { + switch ($action) + { + case 'delete': + $action_subforums = request_var('action_subforums', ''); + $subforums_to_id = request_var('subforums_to_id', 0); + $action_posts = request_var('action_posts', ''); + $posts_to_id = request_var('posts_to_id', 0); + + $errors = $this->delete_forum($forum_id, $action_posts, $action_subforums, $posts_to_id, $subforums_to_id); + + if (sizeof($errors)) + { + break; + } + + $auth->acl_clear_prefetch(); + $cache->destroy('sql', FORUMS_TABLE); + + trigger_error($user->lang['FORUM_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + + break; + + case 'edit': + $forum_data = array( + 'forum_id' => $forum_id + ); + + // No break here + + case 'add': + + $forum_data += array( + 'parent_id' => request_var('forum_parent_id', $this->parent_id), + 'forum_type' => request_var('forum_type', FORUM_POST), + 'type_action' => request_var('type_action', ''), + 'forum_status' => request_var('forum_status', ITEM_UNLOCKED), + 'forum_parents' => '', + 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), + 'forum_link' => request_var('forum_link', ''), + 'forum_link_track' => request_var('forum_link_track', false), + 'forum_desc' => utf8_normalize_nfc(request_var('forum_desc', '', true)), + 'forum_desc_uid' => '', + 'forum_desc_options' => 7, + 'forum_desc_bitfield' => '', + 'forum_rules' => utf8_normalize_nfc(request_var('forum_rules', '', true)), + 'forum_rules_uid' => '', + 'forum_rules_options' => 7, + 'forum_rules_bitfield' => '', + 'forum_rules_link' => request_var('forum_rules_link', ''), + 'forum_image' => request_var('forum_image', ''), + 'forum_style' => request_var('forum_style', 0), + 'display_subforum_list' => request_var('display_subforum_list', false), + 'display_on_index' => request_var('display_on_index', false), + 'forum_topics_per_page' => request_var('topics_per_page', 0), + 'enable_indexing' => request_var('enable_indexing', true), + 'enable_icons' => request_var('enable_icons', false), + 'enable_prune' => request_var('enable_prune', false), + 'enable_post_review' => request_var('enable_post_review', true), + 'prune_days' => request_var('prune_days', 7), + 'prune_viewed' => request_var('prune_viewed', 7), + 'prune_freq' => request_var('prune_freq', 1), + 'prune_old_polls' => request_var('prune_old_polls', false), + 'prune_announce' => request_var('prune_announce', false), + 'prune_sticky' => request_var('prune_sticky', false), + 'forum_password' => request_var('forum_password', '', true), + 'forum_password_confirm'=> request_var('forum_password_confirm', '', true), + 'forum_password_unset' => request_var('forum_password_unset', false), + ); + + // Use link_display_on_index setting if forum type is link + if ($forum_data['forum_type'] == FORUM_LINK) + { + $forum_data['display_on_index'] = request_var('link_display_on_index', false); + } + + // Linked forums and categories are not able to be locked... + if ($forum_data['forum_type'] == FORUM_LINK || $forum_data['forum_type'] == FORUM_CAT) + { + $forum_data['forum_status'] = ITEM_UNLOCKED; + } + + $forum_data['show_active'] = ($forum_data['forum_type'] == FORUM_POST) ? request_var('display_recent', false) : request_var('display_active', false); + + // Get data for forum rules if specified... + if ($forum_data['forum_rules']) + { + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_parse_bbcode', false), request_var('rules_parse_urls', false), request_var('rules_parse_smilies', false)); + } + + // Get data for forum description if specified + if ($forum_data['forum_desc']) + { + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_parse_bbcode', false), request_var('desc_parse_urls', false), request_var('desc_parse_smilies', false)); + } + + $errors = $this->update_forum_data($forum_data); + + if (!sizeof($errors)) + { + $forum_perm_from = request_var('forum_perm_from', 0); + + // Copy permissions? + if ($forum_perm_from && !empty($forum_perm_from) && $forum_perm_from != $forum_data['forum_id'] && + (($action != 'edit') || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth')))) + { + // if we edit a forum delete current permissions first + if ($action == 'edit') + { + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE forum_id = ' . (int) $forum_data['forum_id']; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE forum_id = ' . (int) $forum_data['forum_id']; + $db->sql_query($sql); + } + + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + // Copy permisisons from/to the acl users table (only forum_id gets changed) + $sql = 'SELECT user_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_USERS_TABLE . ' + WHERE forum_id = ' . $forum_perm_from; + $result = $db->sql_query($sql); + + $users_sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $users_sql_ary[] = array( + 'user_id' => (int) $row['user_id'], + 'forum_id' => (int) $forum_data['forum_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'] + ); + } + $db->sql_freeresult($result); + + // Copy permisisons from/to the acl groups table (only forum_id gets changed) + $sql = 'SELECT group_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_GROUPS_TABLE . ' + WHERE forum_id = ' . $forum_perm_from; + $result = $db->sql_query($sql); + + $groups_sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups_sql_ary[] = array( + 'group_id' => (int) $row['group_id'], + 'forum_id' => (int) $forum_data['forum_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'] + ); + } + $db->sql_freeresult($result); + + // Now insert the data + $db->sql_multi_insert(ACL_USERS_TABLE, $users_sql_ary); + $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary); + cache_moderators(); + } + + $auth->acl_clear_prefetch(); + $cache->destroy('sql', FORUMS_TABLE); + + $acl_url = '&mode=setting_forum_local&forum_id[]=' . $forum_data['forum_id']; + + $message = ($action == 'add') ? $user->lang['FORUM_CREATED'] : $user->lang['FORUM_UPDATED']; + + // Redirect to permissions + if ($auth->acl_get('a_fauth')) + { + $message .= '<br /><br />' . sprintf($user->lang['REDIRECT_ACL'], '<a href="' . append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=permissions' . $acl_url) . '">', '</a>'); + } + + // redirect directly to permission settings screen if authed + if ($action == 'add' && !$forum_perm_from && $auth->acl_get('a_fauth')) + { + meta_refresh(4, append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=permissions' . $acl_url)); + } + + trigger_error($message . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + + break; + } + } + + switch ($action) + { + case 'move_up': + case 'move_down': + + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $move_forum_name = $this->move_forum_by($row, $action, 1); + + if ($move_forum_name !== false) + { + add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name); + $cache->destroy('sql', FORUMS_TABLE); + } + + break; + + case 'sync': + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + @set_time_limit(0); + + $sql = 'SELECT forum_name, forum_topics_real + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + if ($row['forum_topics_real']) + { + $sql = 'SELECT MIN(topic_id) as min_topic_id, MAX(topic_id) as max_topic_id + FROM ' . TOPICS_TABLE . ' + WHERE forum_id = ' . $forum_id; + $result = $db->sql_query($sql); + $row2 = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Typecast to int if there is no data available + $row2['min_topic_id'] = (int) $row2['min_topic_id']; + $row2['max_topic_id'] = (int) $row2['max_topic_id']; + + $start = request_var('start', $row2['min_topic_id']); + + $batch_size = 2000; + $end = $start + $batch_size; + + // Sync all topics in batch mode... + sync('topic_approved', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, false); + sync('topic', 'range', 'topic_id BETWEEN ' . $start . ' AND ' . $end, true, true); + + if ($end < $row2['max_topic_id']) + { + // We really need to find a way of showing statistics... no progress here + $sql = 'SELECT COUNT(topic_id) as num_topics + FROM ' . TOPICS_TABLE . ' + WHERE forum_id = ' . $forum_id . ' + AND topic_id BETWEEN ' . $start . ' AND ' . $end; + $result = $db->sql_query($sql); + $topics_done = request_var('topics_done', 0) + (int) $db->sql_fetchfield('num_topics'); + $db->sql_freeresult($result); + + $start += $batch_size; + + $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync&start=$start&topics_done=$topics_done&total={$row['forum_topics_real']}"; + + meta_refresh(0, $url); + + $template->assign_vars(array( + 'U_PROGRESS_BAR' => $this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}", + 'UA_PROGRESS_BAR' => addslashes($this->u_action . "&action=progress_bar&start=$topics_done&total={$row['forum_topics_real']}"), + 'S_CONTINUE_SYNC' => true, + 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $topics_done, $row['forum_topics_real'])) + ); + + return; + } + } + + $url = $this->u_action . "&parent_id={$this->parent_id}&f=$forum_id&action=sync_forum"; + meta_refresh(0, $url); + + $template->assign_vars(array( + 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', + 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), + 'S_CONTINUE_SYNC' => true, + 'L_PROGRESS_EXPLAIN' => sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], 0, $row['forum_topics_real'])) + ); + + return; + + break; + + case 'sync_forum': + + $sql = 'SELECT forum_name, forum_type + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + sync('forum', 'forum_id', $forum_id, false, true); + + add_log('admin', 'LOG_FORUM_SYNC', $row['forum_name']); + $cache->destroy('sql', FORUMS_TABLE); + + $template->assign_var('L_FORUM_RESYNCED', sprintf($user->lang['FORUM_RESYNCED'], $row['forum_name'])); + + break; + + case 'add': + case 'edit': + + if ($update) + { + $forum_data['forum_flags'] = 0; + $forum_data['forum_flags'] += (request_var('forum_link_track', false)) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data['forum_flags'] += (request_var('prune_old_polls', false)) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data['forum_flags'] += (request_var('prune_announce', false)) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data['forum_flags'] += (request_var('prune_sticky', false)) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; + $forum_data['forum_flags'] += (request_var('enable_post_review', true)) ? FORUM_FLAG_POST_REVIEW : 0; + } + + // Show form to create/modify a forum + if ($action == 'edit') + { + $this->page_title = 'EDIT_FORUM'; + $row = $this->get_forum_info($forum_id); + $old_forum_type = $row['forum_type']; + + if (!$update) + { + $forum_data = $row; + } + else + { + $forum_data['left_id'] = $row['left_id']; + $forum_data['right_id'] = $row['right_id']; + } + + // Make sure no direct child forums are able to be selected as parents. + $exclude_forums = array(); + foreach (get_forum_branch($forum_id, 'children') as $row) + { + $exclude_forums[] = $row['forum_id']; + } + + $parents_list = make_forum_select($forum_data['parent_id'], $exclude_forums, false, false, false); + + $forum_data['forum_password_confirm'] = $forum_data['forum_password']; + } + else + { + $this->page_title = 'CREATE_FORUM'; + + $forum_id = $this->parent_id; + $parents_list = make_forum_select($this->parent_id, false, false, false, false); + + // Fill forum data with default values + if (!$update) + { + $forum_data = array( + 'parent_id' => $this->parent_id, + 'forum_type' => FORUM_POST, + 'forum_status' => ITEM_UNLOCKED, + 'forum_name' => utf8_normalize_nfc(request_var('forum_name', '', true)), + 'forum_link' => '', + 'forum_link_track' => false, + 'forum_desc' => '', + 'forum_rules' => '', + 'forum_rules_link' => '', + 'forum_image' => '', + 'forum_style' => 0, + 'display_subforum_list' => true, + 'display_on_index' => false, + 'forum_topics_per_page' => 0, + 'enable_indexing' => true, + 'enable_icons' => false, + 'enable_prune' => false, + 'prune_days' => 7, + 'prune_viewed' => 7, + 'prune_freq' => 1, + 'forum_flags' => FORUM_FLAG_POST_REVIEW, + 'forum_password' => '', + 'forum_password_confirm'=> '', + ); + } + } + + $forum_rules_data = array( + 'text' => $forum_data['forum_rules'], + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + + $forum_desc_data = array( + 'text' => $forum_data['forum_desc'], + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + + $forum_rules_preview = ''; + + // Parse rules if specified + if ($forum_data['forum_rules']) + { + if (!isset($forum_data['forum_rules_uid'])) + { + // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + $forum_data['forum_rules_uid'] = ''; + $forum_data['forum_rules_bitfield'] = ''; + $forum_data['forum_rules_options'] = 0; + + generate_text_for_storage($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options'], request_var('rules_allow_bbcode', false), request_var('rules_allow_urls', false), request_var('rules_allow_smilies', false)); + } + + // Generate preview content + $forum_rules_preview = generate_text_for_display($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options']); + + // decode... + $forum_rules_data = generate_text_for_edit($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_options']); + } + + // Parse desciption if specified + if ($forum_data['forum_desc']) + { + if (!isset($forum_data['forum_desc_uid'])) + { + // Before we are able to display the preview and plane text, we need to parse our request_var()'d value... + $forum_data['forum_desc_uid'] = ''; + $forum_data['forum_desc_bitfield'] = ''; + $forum_data['forum_desc_options'] = 0; + + generate_text_for_storage($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options'], request_var('desc_allow_bbcode', false), request_var('desc_allow_urls', false), request_var('desc_allow_smilies', false)); + } + + // decode... + $forum_desc_data = generate_text_for_edit($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_options']); + } + + $forum_type_options = ''; + $forum_type_ary = array(FORUM_CAT => 'CAT', FORUM_POST => 'FORUM', FORUM_LINK => 'LINK'); + + foreach ($forum_type_ary as $value => $lang) + { + $forum_type_options .= '<option value="' . $value . '"' . (($value == $forum_data['forum_type']) ? ' selected="selected"' : '') . '>' . $user->lang['TYPE_' . $lang] . '</option>'; + } + + $styles_list = style_select($forum_data['forum_style'], true); + + $statuslist = '<option value="' . ITEM_UNLOCKED . '"' . (($forum_data['forum_status'] == ITEM_UNLOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['UNLOCKED'] . '</option><option value="' . ITEM_LOCKED . '"' . (($forum_data['forum_status'] == ITEM_LOCKED) ? ' selected="selected"' : '') . '>' . $user->lang['LOCKED'] . '</option>'; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + AND forum_id <> $forum_id"; + $result = $db->sql_query($sql); + + if ($db->sql_fetchrow($result)) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $forum_id, false, true, false)) + ); + } + $db->sql_freeresult($result); + + // Subforum move options + if ($action == 'edit' && $forum_data['forum_type'] == FORUM_CAT) + { + $subforums_id = array(); + $subforums = get_forum_branch($forum_id, 'children'); + + foreach ($subforums as $row) + { + $subforums_id[] = $row['forum_id']; + } + + $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + AND forum_id <> $forum_id"; + $result = $db->sql_query($sql); + + if ($db->sql_fetchrow($result)) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id)) // , false, true, false??? + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, + 'S_FORUMS_LIST' => $forums_list) + ); + } + + $s_show_display_on_index = false; + + if ($forum_data['parent_id'] > 0) + { + // if this forum is a subforum put the "display on index" checkbox + if ($parent_info = $this->get_forum_info($forum_data['parent_id'])) + { + if ($parent_info['parent_id'] > 0 || $parent_info['forum_type'] == FORUM_CAT) + { + $s_show_display_on_index = true; + } + } + } + + if (strlen($forum_data['forum_password']) == 32) + { + $errors[] = $user->lang['FORUM_PASSWORD_OLD']; + } + + $template->assign_vars(array( + 'S_EDIT_FORUM' => true, + 'S_ERROR' => (sizeof($errors)) ? true : false, + 'S_PARENT_ID' => $this->parent_id, + 'S_FORUM_PARENT_ID' => $forum_data['parent_id'], + 'S_ADD_ACTION' => ($action == 'add') ? true : false, + + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + 'U_EDIT_ACTION' => $this->u_action . "&parent_id={$this->parent_id}&action=$action&f=$forum_id", + + 'L_COPY_PERMISSIONS_EXPLAIN' => $user->lang['COPY_PERMISSIONS_' . strtoupper($action) . '_EXPLAIN'], + 'L_TITLE' => $user->lang[$this->page_title], + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + + 'FORUM_NAME' => $forum_data['forum_name'], + 'FORUM_DATA_LINK' => $forum_data['forum_link'], + 'FORUM_IMAGE' => $forum_data['forum_image'], + 'FORUM_IMAGE_SRC' => ($forum_data['forum_image']) ? PHPBB_ROOT_PATH . $forum_data['forum_image'] : '', + 'FORUM_POST' => FORUM_POST, + 'FORUM_LINK' => FORUM_LINK, + 'FORUM_CAT' => FORUM_CAT, + 'PRUNE_FREQ' => $forum_data['prune_freq'], + 'PRUNE_DAYS' => $forum_data['prune_days'], + 'PRUNE_VIEWED' => $forum_data['prune_viewed'], + 'TOPICS_PER_PAGE' => $forum_data['forum_topics_per_page'], + 'FORUM_RULES_LINK' => $forum_data['forum_rules_link'], + 'FORUM_RULES' => $forum_data['forum_rules'], + 'FORUM_RULES_PREVIEW' => $forum_rules_preview, + 'FORUM_RULES_PLAIN' => $forum_rules_data['text'], + 'S_BBCODE_CHECKED' => ($forum_rules_data['allow_bbcode']) ? true : false, + 'S_SMILIES_CHECKED' => ($forum_rules_data['allow_smilies']) ? true : false, + 'S_URLS_CHECKED' => ($forum_rules_data['allow_urls']) ? true : false, + 'S_FORUM_PASSWORD_SET' => (empty($forum_data['forum_password'])) ? false : true, + + 'FORUM_DESC' => $forum_desc_data['text'], + 'S_DESC_BBCODE_CHECKED' => ($forum_desc_data['allow_bbcode']) ? true : false, + 'S_DESC_SMILIES_CHECKED' => ($forum_desc_data['allow_smilies']) ? true : false, + 'S_DESC_URLS_CHECKED' => ($forum_desc_data['allow_urls']) ? true : false, + + 'S_FORUM_TYPE_OPTIONS' => $forum_type_options, + 'S_STATUS_OPTIONS' => $statuslist, + 'S_PARENT_OPTIONS' => $parents_list, + 'S_STYLES_OPTIONS' => $styles_list, + 'S_FORUM_OPTIONS' => make_forum_select(($action == 'add') ? $forum_data['parent_id'] : false, ($action == 'edit') ? $forum_data['forum_id'] : false, false, false, false), + 'S_SHOW_DISPLAY_ON_INDEX' => $s_show_display_on_index, + 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, + 'S_FORUM_ORIG_POST' => (isset($old_forum_type) && $old_forum_type == FORUM_POST) ? true : false, + 'S_FORUM_ORIG_CAT' => (isset($old_forum_type) && $old_forum_type == FORUM_CAT) ? true : false, + 'S_FORUM_ORIG_LINK' => (isset($old_forum_type) && $old_forum_type == FORUM_LINK) ? true : false, + 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, + 'S_FORUM_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, + 'S_ENABLE_INDEXING' => ($forum_data['enable_indexing']) ? true : false, + 'S_TOPIC_ICONS' => ($forum_data['enable_icons']) ? true : false, + 'S_DISPLAY_SUBFORUM_LIST' => ($forum_data['display_subforum_list']) ? true : false, + 'S_DISPLAY_ON_INDEX' => ($forum_data['display_on_index']) ? true : false, + 'S_PRUNE_ENABLE' => ($forum_data['enable_prune']) ? true : false, + 'S_FORUM_LINK_TRACK' => ($forum_data['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? true : false, + 'S_PRUNE_OLD_POLLS' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_POLL) ? true : false, + 'S_PRUNE_ANNOUNCE' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_ANNOUNCE) ? true : false, + 'S_PRUNE_STICKY' => ($forum_data['forum_flags'] & FORUM_FLAG_PRUNE_STICKY) ? true : false, + 'S_DISPLAY_ACTIVE_TOPICS' => ($forum_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS) ? true : false, + 'S_ENABLE_POST_REVIEW' => ($forum_data['forum_flags'] & FORUM_FLAG_POST_REVIEW) ? true : false, + 'S_CAN_COPY_PERMISSIONS' => ($action != 'edit' || empty($forum_id) || ($auth->acl_get('a_fauth') && $auth->acl_get('a_authusers') && $auth->acl_get('a_authgroups') && $auth->acl_get('a_mauth'))) ? true : false, + )); + + return; + + break; + + case 'delete': + + if (!$forum_id) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $forum_data = $this->get_forum_info($forum_id); + + $subforums_id = array(); + $subforums = get_forum_branch($forum_id, 'children'); + + foreach ($subforums as $row) + { + $subforums_id[] = $row['forum_id']; + } + + $forums_list = make_forum_select($forum_data['parent_id'], $subforums_id); + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + AND forum_id <> $forum_id"; + $result = $db->sql_query($sql); + + if ($db->sql_fetchrow($result)) + { + $template->assign_vars(array( + 'S_MOVE_FORUM_OPTIONS' => make_forum_select($forum_data['parent_id'], $subforums_id, false, true)) // , false, true, false??? + ); + } + $db->sql_freeresult($result); + + $parent_id = ($this->parent_id == $forum_id) ? 0 : $this->parent_id; + + $template->assign_vars(array( + 'S_DELETE_FORUM' => true, + 'U_ACTION' => $this->u_action . "&parent_id={$parent_id}&action=delete&f=$forum_id", + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'FORUM_NAME' => $forum_data['forum_name'], + 'S_FORUM_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, + 'S_FORUM_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, + 'S_HAS_SUBFORUMS' => ($forum_data['right_id'] - $forum_data['left_id'] > 1) ? true : false, + 'S_FORUMS_LIST' => $forums_list, + 'S_ERROR' => (sizeof($errors)) ? true : false, + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '') + ); + + return; + break; + } + + // Default management page + if (!$this->parent_id) + { + $navigation = $user->lang['FORUM_INDEX']; + } + else + { + $navigation = '<a href="' . $this->u_action . '">' . $user->lang['FORUM_INDEX'] . '</a>'; + + $forums_nav = get_forum_branch($this->parent_id, 'parents', 'descending'); + foreach ($forums_nav as $row) + { + if ($row['forum_id'] == $this->parent_id) + { + $navigation .= ' -> ' . $row['forum_name']; + } + else + { + $navigation .= ' -> <a href="' . $this->u_action . '&parent_id=' . $row['forum_id'] . '">' . $row['forum_name'] . '</a>'; + } + } + } + + // Jumpbox + $forum_box = make_forum_select($this->parent_id, false, false, false, false); //make_forum_select($this->parent_id); + + if ($action == 'sync' || $action == 'sync_forum') + { + $template->assign_var('S_RESYNCED', true); + } + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE parent_id = $this->parent_id + ORDER BY left_id"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $forum_type = $row['forum_type']; + + if ($row['forum_status'] == ITEM_LOCKED) + { + $folder_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['LOCKED'] . '" />'; + } + else + { + switch ($forum_type) + { + case FORUM_LINK: + $folder_image = '<img src="images/icon_folder_link.gif" alt="' . $user->lang['LINK'] . '" />'; + break; + + default: + $folder_image = ($row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['SUBFORUM'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['FOLDER'] . '" />'; + break; + } + } + + $url = $this->u_action . "&parent_id=$this->parent_id&f={$row['forum_id']}"; + + $forum_title = ($forum_type != FORUM_LINK) ? '<a href="' . $this->u_action . '&parent_id=' . $row['forum_id'] . '">' : ''; + $forum_title .= $row['forum_name']; + $forum_title .= ($forum_type != FORUM_LINK) ? '</a>' : ''; + + $template->assign_block_vars('forums', array( + 'FOLDER_IMAGE' => $folder_image, + 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . PHPBB_ROOT_PATH . $row['forum_image'] . '" alt="" />' : '', + 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? PHPBB_ROOT_PATH . $row['forum_image'] : '', + 'FORUM_NAME' => $row['forum_name'], + 'FORUM_DESCRIPTION' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), + 'FORUM_TOPICS' => $row['forum_topics'], + 'FORUM_POSTS' => $row['forum_posts'], + + 'S_FORUM_LINK' => ($forum_type == FORUM_LINK) ? true : false, + 'S_FORUM_POST' => ($forum_type == FORUM_POST) ? true : false, + + 'U_FORUM' => $this->u_action . '&parent_id=' . $row['forum_id'], + 'U_MOVE_UP' => $url . '&action=move_up', + 'U_MOVE_DOWN' => $url . '&action=move_down', + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_SYNC' => $url . '&action=sync') + ); + } + while ($row = $db->sql_fetchrow($result)); + } + else if ($this->parent_id) + { + $row = $this->get_forum_info($this->parent_id); + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&f=' . $row['forum_id']; + + $template->assign_vars(array( + 'S_NO_FORUMS' => true, + + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_SYNC' => $url . '&action=sync') + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'ERROR_MSG' => (sizeof($errors)) ? implode('<br />', $errors) : '', + 'NAVIGATION' => $navigation, + 'FORUM_BOX' => $forum_box, + 'U_SEL_ACTION' => $this->u_action, + 'U_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'U_PROGRESS_BAR' => $this->u_action . '&action=progress_bar', + 'UA_PROGRESS_BAR' => addslashes($this->u_action . '&action=progress_bar'), + )); + } + + /** + * Get forum details + */ + function get_forum_info($forum_id) + { + global $db; + + $sql = 'SELECT * + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error("Forum #$forum_id does not exist", E_USER_ERROR); + } + + return $row; + } + + /** + * Update forum data + */ + function update_forum_data(&$forum_data) + { + global $db, $user, $cache; + + $errors = array(); + + if (!$forum_data['forum_name']) + { + $errors[] = $user->lang['FORUM_NAME_EMPTY']; + } + + if (utf8_strlen($forum_data['forum_desc']) > 4000) + { + $errors[] = $user->lang['FORUM_DESC_TOO_LONG']; + } + + if (utf8_strlen($forum_data['forum_rules']) > 4000) + { + $errors[] = $user->lang['FORUM_RULES_TOO_LONG']; + } + + if ($forum_data['forum_password'] || $forum_data['forum_password_confirm']) + { + if ($forum_data['forum_password'] != $forum_data['forum_password_confirm']) + { + $forum_data['forum_password'] = $forum_data['forum_password_confirm'] = ''; + $errors[] = $user->lang['FORUM_PASSWORD_MISMATCH']; + } + } + + if ($forum_data['prune_days'] < 0 || $forum_data['prune_viewed'] < 0 || $forum_data['prune_freq'] < 0) + { + $forum_data['prune_days'] = $forum_data['prune_viewed'] = $forum_data['prune_freq'] = 0; + $errors[] = $user->lang['FORUM_DATA_NEGATIVE']; + } + + $range_test_ary = array( + array('lang' => 'FORUM_TOPICS_PAGE', 'value' => $forum_data['forum_topics_per_page'], 'column_type' => 'TINT:0'), + ); + + validate_range($range_test_ary, $errors); + + // Set forum flags + // 1 = link tracking + // 2 = prune old polls + // 4 = prune announcements + // 8 = prune stickies + // 16 = show active topics + // 32 = enable post review + $forum_data['forum_flags'] = 0; + $forum_data['forum_flags'] += ($forum_data['forum_link_track']) ? FORUM_FLAG_LINK_TRACK : 0; + $forum_data['forum_flags'] += ($forum_data['prune_old_polls']) ? FORUM_FLAG_PRUNE_POLL : 0; + $forum_data['forum_flags'] += ($forum_data['prune_announce']) ? FORUM_FLAG_PRUNE_ANNOUNCE : 0; + $forum_data['forum_flags'] += ($forum_data['prune_sticky']) ? FORUM_FLAG_PRUNE_STICKY : 0; + $forum_data['forum_flags'] += ($forum_data['show_active']) ? FORUM_FLAG_ACTIVE_TOPICS : 0; + $forum_data['forum_flags'] += ($forum_data['enable_post_review']) ? FORUM_FLAG_POST_REVIEW : 0; + + // Unset data that are not database fields + $forum_data_sql = $forum_data; + + unset($forum_data_sql['forum_link_track']); + unset($forum_data_sql['prune_old_polls']); + unset($forum_data_sql['prune_announce']); + unset($forum_data_sql['prune_sticky']); + unset($forum_data_sql['show_active']); + unset($forum_data_sql['enable_post_review']); + unset($forum_data_sql['forum_password_confirm']); + + // What are we going to do tonight Brain? The same thing we do everynight, + // try to take over the world ... or decide whether to continue update + // and if so, whether it's a new forum/cat/link or an existing one + if (sizeof($errors)) + { + return $errors; + } + + // As we don't know the old password, it's kinda tricky to detect changes + if ($forum_data_sql['forum_password_unset']) + { + $forum_data_sql['forum_password'] = ''; + } + else if (empty($forum_data_sql['forum_password'])) + { + unset($forum_data_sql['forum_password']); + } + else + { + $forum_data_sql['forum_password'] = phpbb_hash($forum_data_sql['forum_password']); + } + unset($forum_data_sql['forum_password_unset']); + + if (!isset($forum_data_sql['forum_id'])) + { + // no forum_id means we're creating a new forum + unset($forum_data_sql['type_action']); + + if ($forum_data_sql['parent_id']) + { + $sql = 'SELECT left_id, right_id, forum_type + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $forum_data_sql['parent_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['PARENT_NOT_EXIST'] . adm_back_link($this->u_action . '&' . $this->parent_id), E_USER_WARNING); + } + + if ($row['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; + return $errors; + } + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET left_id = left_id + 2, right_id = right_id + 2 + WHERE left_id > ' . $row['right_id']; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET right_id = right_id + 2 + WHERE ' . $row['left_id'] . ' BETWEEN left_id AND right_id'; + $db->sql_query($sql); + + $forum_data_sql['left_id'] = $row['right_id']; + $forum_data_sql['right_id'] = $row['right_id'] + 1; + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $forum_data_sql['left_id'] = $row['right_id'] + 1; + $forum_data_sql['right_id'] = $row['right_id'] + 2; + } + + $sql = 'INSERT INTO ' . FORUMS_TABLE . ' ' . $db->sql_build_array('INSERT', $forum_data_sql); + $db->sql_query($sql); + + $forum_data['forum_id'] = $db->sql_nextid(); + + add_log('admin', 'LOG_FORUM_ADD', $forum_data['forum_name']); + } + else + { + $row = $this->get_forum_info($forum_data_sql['forum_id']); + + if ($row['forum_type'] == FORUM_POST && $row['forum_type'] != $forum_data_sql['forum_type']) + { + // Has subforums and want to change into a link? + if ($row['right_id'] - $row['left_id'] > 1 && $forum_data_sql['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['FORUM_WITH_SUBFORUMS_NOT_TO_LINK']; + return $errors; + } + + // we're turning a postable forum into a non-postable forum + if ($forum_data_sql['type_action'] == 'move') + { + $to_forum_id = request_var('to_forum_id', 0); + + if ($to_forum_id) + { + $errors = $this->move_forum_content($forum_data_sql['forum_id'], $to_forum_id); + } + else + { + return array($user->lang['NO_DESTINATION_FORUM']); + } + } + else if ($forum_data_sql['type_action'] == 'delete') + { + $errors = $this->delete_forum_content($forum_data_sql['forum_id']); + } + else + { + return array($user->lang['NO_FORUM_ACTION']); + } + + $forum_data_sql['forum_posts'] = $forum_data_sql['forum_topics'] = $forum_data_sql['forum_topics_real'] = $forum_data_sql['forum_last_post_id'] = $forum_data_sql['forum_last_poster_id'] = $forum_data_sql['forum_last_post_time'] = 0; + $forum_data_sql['forum_last_poster_name'] = $forum_data_sql['forum_last_poster_colour'] = ''; + } + else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_LINK) + { + // Has subforums? + if ($row['right_id'] - $row['left_id'] > 1) + { + // We are turning a category into a link - but need to decide what to do with the subforums. + $action_subforums = request_var('action_subforums', ''); + $subforums_to_id = request_var('subforums_to_id', 0); + + if ($action_subforums == 'delete') + { + $rows = get_forum_branch($row['forum_id'], 'children', 'descending', false); + + foreach ($rows as $_row) + { + // Do not remove the forum id we are about to change. ;) + if ($_row['forum_id'] == $row['forum_id']) + { + continue; + } + + $forum_ids[] = $_row['forum_id']; + $errors = array_merge($errors, $this->delete_forum_content($_row['forum_id'])); + } + + if (sizeof($errors)) + { + return $errors; + } + + if (sizeof($forum_ids)) + { + $sql = 'DELETE FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + // Delete forum ids from extension groups table + $sql = 'SELECT group_id, allowed_forums + FROM ' . EXTENSION_GROUPS_TABLE; + $result = $db->sql_query($sql); + + while ($_row = $db->sql_fetchrow($result)) + { + if (!$_row['allowed_forums']) + { + continue; + } + + $allowed_forums = unserialize(trim($_row['allowed_forums'])); + $allowed_forums = array_diff($allowed_forums, $forum_ids); + + $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " + SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + WHERE group_id = {$_row['group_id']}"; + $db->sql_query($sql); + } + $db->sql_freeresult($result); + + $cache->destroy('_extensions'); + } + } + else if ($action_subforums == 'move') + { + if (!$subforums_to_id) + { + return array($user->lang['NO_DESTINATION_FORUM']); + } + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $subforums_to_id; + $result = $db->sql_query($sql); + $_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$_row) + { + return array($user->lang['NO_FORUM']); + } + + $subforums_to_name = $_row['forum_name']; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = {$row['forum_id']}"; + $result = $db->sql_query($sql); + + while ($_row = $db->sql_fetchrow($result)) + { + $this->move_forum($_row['forum_id'], $subforums_to_id); + } + $db->sql_freeresult($result); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET parent_id = $subforums_to_id + WHERE parent_id = {$row['forum_id']}"; + $db->sql_query($sql); + } + + // Adjust the left/right id + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET right_id = left_id + 1 + WHERE forum_id = ' . $row['forum_id']; + $db->sql_query($sql); + } + } + else if ($row['forum_type'] == FORUM_CAT && $forum_data_sql['forum_type'] == FORUM_POST) + { + // Changing a category to a forum? Reset the data (you can't post directly in a cat, you must use a forum) + $forum_data_sql['forum_posts'] = 0; + $forum_data_sql['forum_topics'] = 0; + $forum_data_sql['forum_topics_real'] = 0; + $forum_data_sql['forum_last_post_id'] = 0; + $forum_data_sql['forum_last_post_subject'] = ''; + $forum_data_sql['forum_last_post_time'] = 0; + $forum_data_sql['forum_last_poster_id'] = 0; + $forum_data_sql['forum_last_poster_name'] = ''; + $forum_data_sql['forum_last_poster_colour'] = ''; + } + + if (sizeof($errors)) + { + return $errors; + } + + if ($row['parent_id'] != $forum_data_sql['parent_id']) + { + if ($row['forum_id'] != $forum_data_sql['parent_id']) + { + $errors = $this->move_forum($forum_data_sql['forum_id'], $forum_data_sql['parent_id']); + } + else + { + $forum_data_sql['parent_id'] = $row['parent_id']; + } + } + + if (sizeof($errors)) + { + return $errors; + } + + unset($forum_data_sql['type_action']); + + if ($row['forum_name'] != $forum_data_sql['forum_name']) + { + // the forum name has changed, clear the parents list of all forums (for safety) + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_parents = ''"; + $db->sql_query($sql); + } + + // Setting the forum id to the forum id is not really received well by some dbs. ;) + $forum_id = $forum_data_sql['forum_id']; + unset($forum_data_sql['forum_id']); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $forum_data_sql) . ' + WHERE forum_id = ' . $forum_id; + $db->sql_query($sql); + + // Add it back + $forum_data['forum_id'] = $forum_id; + + add_log('admin', 'LOG_FORUM_EDIT', $forum_data['forum_name']); + } + + return $errors; + } + + /** + * Move forum + */ + function move_forum($from_id, $to_id) + { + global $db, $user; + + $to_data = $moved_ids = $errors = array(); + + // Check if we want to move to a parent with link type + if ($to_id > 0) + { + $to_data = $this->get_forum_info($to_id); + + if ($to_data['forum_type'] == FORUM_LINK) + { + $errors[] = $user->lang['PARENT_IS_LINK_FORUM']; + return $errors; + } + } + + $moved_forums = get_forum_branch($from_id, 'children', 'descending'); + $from_data = $moved_forums[0]; + $diff = sizeof($moved_forums) * 2; + + $moved_ids = array(); + for ($i = 0; $i < sizeof($moved_forums); ++$i) + { + $moved_ids[] = $moved_forums[$i]['forum_id']; + } + + // Resync parents + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id - $diff, forum_parents = '' + WHERE left_id < " . $from_data['right_id'] . " + AND right_id > " . $from_data['right_id']; + $db->sql_query($sql); + + // Resync righthand side of tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff, forum_parents = '' + WHERE left_id > " . $from_data['right_id']; + $db->sql_query($sql); + + if ($to_id > 0) + { + // Retrieve $to_data again, it may have been changed... + $to_data = $this->get_forum_info($to_id); + + // Resync new parents + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id + $diff, forum_parents = '' + WHERE " . $to_data['right_id'] . ' BETWEEN left_id AND right_id + AND ' . $db->sql_in_set('forum_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync the righthand side of the tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id + $diff, right_id = right_id + $diff, forum_parents = '' + WHERE left_id > " . $to_data['right_id'] . ' + AND ' . $db->sql_in_set('forum_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync moved branch + $to_data['right_id'] += $diff; + + if ($to_data['right_id'] > $from_data['right_id']) + { + $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); + } + else + { + $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); + } + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $moved_ids, true); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $diff = '+ ' . ($row['right_id'] - $from_data['left_id'] + 1); + } + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id $diff, right_id = right_id $diff, forum_parents = '' + WHERE " . $db->sql_in_set('forum_id', $moved_ids); + $db->sql_query($sql); + + return $errors; + } + + /** + * Move forum content from one to another forum + */ + function move_forum_content($from_id, $to_id, $sync = true) + { + global $db; + + $table_ary = array(LOG_TABLE, POSTS_TABLE, TOPICS_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); + + foreach ($table_ary as $table) + { + $sql = "UPDATE $table + SET forum_id = $to_id + WHERE forum_id = $from_id"; + $db->sql_query($sql); + } + unset($table_ary); + + $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, MODERATOR_CACHE_TABLE); + + foreach ($table_ary as $table) + { + $sql = "DELETE FROM $table + WHERE forum_id = $from_id"; + $db->sql_query($sql); + } + + if ($sync) + { + // Delete ghost topics that link back to the same forum then resync counters + sync('topic_moved'); + sync('forum', 'forum_id', $to_id, false, true); + } + + return array(); + } + + /** + * Remove complete forum + */ + function delete_forum($forum_id, $action_posts = 'delete', $action_subforums = 'delete', $posts_to_id = 0, $subforums_to_id = 0) + { + global $db, $user, $cache; + + $forum_data = $this->get_forum_info($forum_id); + + $errors = array(); + $log_action_posts = $log_action_forums = $posts_to_name = $subforums_to_name = ''; + $forum_ids = array($forum_id); + + if ($action_posts == 'delete') + { + $log_action_posts = 'POSTS'; + $errors = array_merge($errors, $this->delete_forum_content($forum_id)); + } + else if ($action_posts == 'move') + { + if (!$posts_to_id) + { + $errors[] = $user->lang['NO_DESTINATION_FORUM']; + } + else + { + $log_action_posts = 'MOVE_POSTS'; + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $posts_to_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $errors[] = $user->lang['NO_FORUM']; + } + else + { + $posts_to_name = $row['forum_name']; + $errors = array_merge($errors, $this->move_forum_content($forum_id, $posts_to_id)); + } + } + } + + if (sizeof($errors)) + { + return $errors; + } + + if ($action_subforums == 'delete') + { + $log_action_forums = 'FORUMS'; + $rows = get_forum_branch($forum_id, 'children', 'descending', false); + + foreach ($rows as $row) + { + $forum_ids[] = $row['forum_id']; + $errors = array_merge($errors, $this->delete_forum_content($row['forum_id'])); + } + + if (sizeof($errors)) + { + return $errors; + } + + $diff = sizeof($forum_ids) * 2; + + $sql = 'DELETE FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_ids); + $db->sql_query($sql); + } + else if ($action_subforums == 'move') + { + if (!$subforums_to_id) + { + $errors[] = $user->lang['NO_DESTINATION_FORUM']; + } + else + { + $log_action_forums = 'MOVE_FORUMS'; + + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . $subforums_to_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $errors[] = $user->lang['NO_FORUM']; + } + else + { + $subforums_to_name = $row['forum_name']; + + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = $forum_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $this->move_forum($row['forum_id'], $subforums_to_id); + } + $db->sql_freeresult($result); + + // Grab new forum data for correct tree updating later + $forum_data = $this->get_forum_info($forum_id); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET parent_id = $subforums_to_id + WHERE parent_id = $forum_id"; + $db->sql_query($sql); + + $diff = 2; + $sql = 'DELETE FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + } + } + + if (sizeof($errors)) + { + return $errors; + } + } + else + { + $diff = 2; + $sql = 'DELETE FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . " + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + } + + // Resync tree + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET right_id = right_id - $diff + WHERE left_id < {$forum_data['right_id']} AND right_id > {$forum_data['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE left_id > {$forum_data['right_id']}"; + $db->sql_query($sql); + + // Delete forum ids from extension groups table + $sql = 'SELECT group_id, allowed_forums + FROM ' . EXTENSION_GROUPS_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$row['allowed_forums']) + { + continue; + } + + $allowed_forums = unserialize(trim($row['allowed_forums'])); + $allowed_forums = array_diff($allowed_forums, $forum_ids); + + $sql = 'UPDATE ' . EXTENSION_GROUPS_TABLE . " + SET allowed_forums = '" . ((sizeof($allowed_forums)) ? serialize($allowed_forums) : '') . "' + WHERE group_id = {$row['group_id']}"; + $db->sql_query($sql); + } + $db->sql_freeresult($result); + + $cache->destroy('_extensions'); + + $log_action = implode('_', array($log_action_posts, $log_action_forums)); + + switch ($log_action) + { + case 'MOVE_POSTS_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_MOVE_FORUMS', $posts_to_name, $subforums_to_name, $forum_data['forum_name']); + break; + + case 'MOVE_POSTS_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS_FORUMS', $posts_to_name, $forum_data['forum_name']); + break; + + case 'POSTS_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_POSTS_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + break; + + case '_MOVE_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_MOVE_FORUMS', $subforums_to_name, $forum_data['forum_name']); + break; + + case 'MOVE_POSTS_': + add_log('admin', 'LOG_FORUM_DEL_MOVE_POSTS', $posts_to_name, $forum_data['forum_name']); + break; + + case 'POSTS_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_POSTS_FORUMS', $forum_data['forum_name']); + break; + + case '_FORUMS': + add_log('admin', 'LOG_FORUM_DEL_FORUMS', $forum_data['forum_name']); + break; + + case 'POSTS_': + add_log('admin', 'LOG_FORUM_DEL_POSTS', $forum_data['forum_name']); + break; + + default: + add_log('admin', 'LOG_FORUM_DEL_FORUM', $forum_data['forum_name']); + break; + } + + return $errors; + } + + /** + * Delete forum content + */ + function delete_forum_content($forum_id) + { + global $db, $config; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + + $db->sql_transaction('begin'); + + // Select then delete all attachments + $sql = 'SELECT a.topic_id + FROM ' . POSTS_TABLE . ' p, ' . ATTACHMENTS_TABLE . " a + WHERE p.forum_id = $forum_id + AND a.in_message = 0 + AND a.topic_id = p.topic_id"; + $result = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + delete_attachments('topic', $topic_ids, false); + + // Before we remove anything we make sure we are able to adjust the post counts later. ;) + $sql = 'SELECT poster_id + FROM ' . POSTS_TABLE . ' + WHERE forum_id = ' . $forum_id . ' + AND post_postcount = 1 + AND post_approved = 1'; + $result = $db->sql_query($sql); + + $post_counts = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; + } + $db->sql_freeresult($result); + + switch ($db->dbms_type) + { + case 'mysql': + + // Delete everything else and thank MySQL for offering multi-table deletion + $tables_ary = array( + SEARCH_WORDMATCH_TABLE => 'post_id', + REPORTS_TABLE => 'post_id', + WARNINGS_TABLE => 'post_id', + BOOKMARKS_TABLE => 'topic_id', + TOPICS_WATCH_TABLE => 'topic_id', + TOPICS_POSTED_TABLE => 'topic_id', + POLL_OPTIONS_TABLE => 'topic_id', + POLL_VOTES_TABLE => 'topic_id', + ); + + $sql = 'DELETE ' . POSTS_TABLE; + $sql_using = "\nFROM " . POSTS_TABLE; + $sql_where = "\nWHERE " . POSTS_TABLE . ".forum_id = $forum_id\n"; + + foreach ($tables_ary as $table => $field) + { + $sql .= ", $table "; + $sql_using .= ", $table "; + $sql_where .= "\nAND $table.$field = " . POSTS_TABLE . ".$field"; + } + + $db->sql_query($sql . $sql_using . $sql_where); + + break; + + default: + + // Delete everything else and curse your DB for not offering multi-table deletion + $tables_ary = array( + 'post_id' => array( + SEARCH_WORDMATCH_TABLE, + REPORTS_TABLE, + WARNINGS_TABLE, + ), + + 'topic_id' => array( + BOOKMARKS_TABLE, + TOPICS_WATCH_TABLE, + TOPICS_POSTED_TABLE, + POLL_OPTIONS_TABLE, + POLL_VOTES_TABLE, + ) + ); + + foreach ($tables_ary as $field => $tables) + { + $start = 0; + + do + { + $sql = "SELECT $field + FROM " . POSTS_TABLE . ' + WHERE forum_id = ' . $forum_id; + $result = $db->sql_query_limit($sql, 500, $start); + + $ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = $row[$field]; + } + $db->sql_freeresult($result); + + if (sizeof($ids)) + { + $start += sizeof($ids); + + foreach ($tables as $table) + { + $db->sql_query("DELETE FROM $table WHERE " . $db->sql_in_set($field, $ids)); + } + } + } + while ($row); + } + unset($ids); + + break; + } + + $table_ary = array(FORUMS_ACCESS_TABLE, FORUMS_TRACK_TABLE, FORUMS_WATCH_TABLE, LOG_TABLE, MODERATOR_CACHE_TABLE, POSTS_TABLE, TOPICS_TABLE, TOPICS_TRACK_TABLE); + + foreach ($table_ary as $table) + { + $db->sql_query("DELETE FROM $table WHERE forum_id = $forum_id"); + } + + // Set forum ids to 0 + $table_ary = array(DRAFTS_TABLE); + + foreach ($table_ary as $table) + { + $db->sql_query("UPDATE $table SET forum_id = 0 WHERE forum_id = $forum_id"); + } + + // Adjust users post counts + if (sizeof($post_counts)) + { + foreach ($post_counts as $poster_id => $substract) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = 0 + WHERE user_id = ' . $poster_id . ' + AND user_posts < ' . $substract; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - ' . $substract . ' + WHERE user_id = ' . $poster_id . ' + AND user_posts >= ' . $substract; + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + // Make sure the overall post/topic count is correct... + $sql = 'SELECT COUNT(post_id) AS stat + FROM ' . POSTS_TABLE . ' + WHERE post_approved = 1'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('num_posts', (int) $row['stat'], true); + + $sql = 'SELECT COUNT(topic_id) AS stat + FROM ' . TOPICS_TABLE . ' + WHERE topic_approved = 1'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('num_topics', (int) $row['stat'], true); + + $sql = 'SELECT COUNT(attach_id) as stat + FROM ' . ATTACHMENTS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('num_files', (int) $row['stat'], true); + + $sql = 'SELECT SUM(filesize) as stat + FROM ' . ATTACHMENTS_TABLE; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + set_config('upload_dir_size', (float) $row['stat'], true); + + return array(); + } + + /** + * Move forum position by $steps up/down + */ + function move_forum_by($forum_row, $action = 'move_up', $steps = 1) + { + global $db; + + /** + * Fetch all the siblings between the module's current spot + * and where we want to move it to. If there are less than $steps + * siblings between the current spot and the target then the + * module will move as far as possible + */ + $sql = 'SELECT forum_id, forum_name, left_id, right_id + FROM ' . FORUMS_TABLE . " + WHERE parent_id = {$forum_row['parent_id']} + AND " . (($action == 'move_up') ? "right_id < {$forum_row['right_id']} ORDER BY right_id DESC" : "left_id > {$forum_row['left_id']} ORDER BY left_id ASC"); + $result = $db->sql_query_limit($sql, $steps); + + $target = array(); + while ($row = $db->sql_fetchrow($result)) + { + $target = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($target)) + { + // The forum is already on top or bottom + return false; + } + + /** + * $left_id and $right_id define the scope of the nodes that are affected by the move. + * $diff_up and $diff_down are the values to substract or add to each node's left_id + * and right_id in order to move them up or down. + * $move_up_left and $move_up_right define the scope of the nodes that are moving + * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. + */ + if ($action == 'move_up') + { + $left_id = $target['left_id']; + $right_id = $forum_row['right_id']; + + $diff_up = $forum_row['left_id'] - $target['left_id']; + $diff_down = $forum_row['right_id'] + 1 - $forum_row['left_id']; + + $move_up_left = $forum_row['left_id']; + $move_up_right = $forum_row['right_id']; + } + else + { + $left_id = $forum_row['left_id']; + $right_id = $target['right_id']; + + $diff_up = $forum_row['right_id'] + 1 - $forum_row['left_id']; + $diff_down = $target['right_id'] - $forum_row['right_id']; + + $move_up_left = $forum_row['right_id'] + 1; + $move_up_right = $target['right_id']; + } + + // Now do the dirty job + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET left_id = left_id + CASE + WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + right_id = right_id + CASE + WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + forum_parents = '' + WHERE + left_id BETWEEN {$left_id} AND {$right_id} + AND right_id BETWEEN {$left_id} AND {$right_id}"; + $db->sql_query($sql); + + return $target['forum_name']; + } + + /** + * Display progress bar for syncinc forums + */ + function display_progress_bar($start, $total) + { + global $template, $user; + + adm_page_header($user->lang['SYNC_IN_PROGRESS']); + + $template->set_filenames(array( + 'body' => 'progress_bar.html') + ); + + $template->assign_vars(array( + 'L_PROGRESS' => $user->lang['SYNC_IN_PROGRESS'], + 'L_PROGRESS_EXPLAIN' => ($start && $total) ? sprintf($user->lang['SYNC_IN_PROGRESS_EXPLAIN'], $start, $total) : $user->lang['SYNC_IN_PROGRESS']) + ); + + adm_page_footer(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_groups.php b/phpBB/modules/acp/acp_groups.php new file mode 100644 index 0000000000..654fd62553 --- /dev/null +++ b/phpBB/modules/acp/acp_groups.php @@ -0,0 +1,772 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_groups +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache, $file_uploads; + + $user->add_lang('acp/groups'); + $this->tpl_name = 'acp_groups'; + $this->page_title = 'ACP_GROUPS_MANAGE'; + + $form_key = 'acp_groups'; + add_form_key($form_key); + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + // Check and set some common vars + $action = (request::is_set_post('add')) ? 'add' : ((request::is_set_post('addusers')) ? 'addusers' : request_var('action', '')); + $group_id = request_var('g', 0); + $mark_ary = request_var('mark', array(0)); + $name_ary = request_var('usernames', '', true); + $leader = request_var('leader', 0); + $default = request_var('default', 0); + $start = request_var('start', 0); + $update = request::is_set_post('update'); + + + // Clear some vars + $can_upload = (file_exists(PHPBB_ROOT_PATH . $config['avatar_path']) && @is_writable(PHPBB_ROOT_PATH . $config['avatar_path']) && $file_uploads) ? true : false; + $group_row = array(); + + // Grab basic data for group, if group_id is set and exists + if ($group_id) + { + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Check if the user is allowed to manage this group if set to founder only. + if ($user->data['user_type'] != USER_FOUNDER && $group_row['group_founder_manage']) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // Which page? + switch ($action) + { + case 'approve': + case 'demote': + case 'promote': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Approve, demote or promote + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $error = group_user_attributes($action, $group_id, $mark_ary, false, $group_name); + + if (!$error) + { + switch ($action) + { + case 'demote': + $message = 'GROUP_MODS_DEMOTED'; + break; + + case 'promote': + $message = 'GROUP_MODS_PROMOTED'; + break; + + case 'approve': + $message = 'USERS_APPROVED'; + break; + } + + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + } + else + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + break; + + case 'default': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (!sizeof($mark_ary)) + { + $start = 0; + + do + { + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + ORDER BY user_id"; + $result = $db->sql_query_limit($sql, 200, $start); + + $mark_ary = array(); + if ($row = $db->sql_fetchrow($result)) + { + do + { + $mark_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); + + $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + } + else + { + group_user_attributes('default', $group_id, $mark_ary, false, $group_name, $group_row); + } + + trigger_error($user->lang['GROUP_DEFS_UPDATED'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + break; + + case 'deleteusers': + case 'delete': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + else if ($action === 'delete' && $group_row['group_type'] == GROUP_SPECIAL) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $error = ''; + + switch ($action) + { + case 'delete': + if (!$auth->acl_get('a_groupdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = group_delete($group_id, $group_row['group_name']); + break; + + case 'deleteusers': + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + $error = group_user_del($group_id, $mark_ary, false, $group_name); + break; + } + + $back_link = ($action == 'delete') ? $this->u_action : $this->u_action . '&action=list&g=' . $group_id; + + if ($error) + { + trigger_error($user->lang[$error] . adm_back_link($back_link), E_USER_WARNING); + } + + $message = ($action == 'delete') ? 'GROUP_DELETED' : 'GROUP_USERS_REMOVE'; + trigger_error($user->lang[$message] . adm_back_link($back_link)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + break; + + case 'addusers': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$name_ary) + { + trigger_error($user->lang['NO_USERS'] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + $name_ary = array_unique(explode("\n", $name_ary)); + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + // Add user/s to group + if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, $leader, 0, $group_row)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&action=list&g=' . $group_id), E_USER_WARNING); + } + + $message = ($leader) ? 'GROUP_MODS_ADDED' : 'GROUP_USERS_ADDED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&action=list&g=' . $group_id)); + break; + + case 'edit': + case 'add': + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $data = $submit_ary = array(); + + if ($action == 'edit' && !$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($action == 'add' && !$auth->acl_get('a_groupadd')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = array(); + $user->add_lang('ucp'); + + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + // Did we submit? + if ($update) + { + if (!check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); + $group_type = request_var('group_type', GROUP_FREE); + + $allow_desc_bbcode = request_var('desc_parse_bbcode', false); + $allow_desc_urls = request_var('desc_parse_urls', false); + $allow_desc_smilies = request_var('desc_parse_smilies', false); + + $data['uploadurl'] = request_var('uploadurl', ''); + $data['remotelink'] = request_var('remotelink', ''); + $data['width'] = request_var('width', ''); + $data['height'] = request_var('height', ''); + $delete = request_var('delete', ''); + + $submit_ary = array( + 'colour' => request_var('group_colour', ''), + 'rank' => request_var('group_rank', 0), + 'receive_pm' => request::is_set('group_receive_pm') ? 1 : 0, + 'legend' => request::is_set('group_legend') ? 1 : 0, + 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients' => request_var('group_max_recipients', 0), + 'founder_manage' => 0, + ); + + if ($user->data['user_type'] == USER_FOUNDER) + { + $submit_ary['founder_manage'] = request::is_set('group_founder_manage') ? 1 : 0; + } + + if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) + { + // Avatar stuff + $var_ary = array( + 'uploadurl' => array('string', true, 5, 255), + 'remotelink' => array('string', true, 5, 255), + 'width' => array('string', true, 1, 3), + 'height' => array('string', true, 1, 3), + ); + + if (!($error = validate_data($data, $var_ary))) + { + $data['user_id'] = "g$group_id"; + + if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_upload($data, $error); + } + else if ($data['remotelink']) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_remote($data, $error); + } + } + } + else if ($avatar_select && $config['allow_avatar_local']) + { + // check avatar gallery + if (is_dir(PHPBB_ROOT_PATH . $config['avatar_gallery_path'] . '/' . $category)) + { + $submit_ary['avatar_type'] = AVATAR_GALLERY; + + list($submit_ary['avatar_width'], $submit_ary['avatar_height']) = getimagesize(PHPBB_ROOT_PATH . $config['avatar_gallery_path'] . '/' . $category . '/' . $avatar_select); + $submit_ary['avatar'] = $category . '/' . $avatar_select; + } + } + else if ($delete) + { + $submit_ary['avatar'] = ''; + $submit_ary['avatar_type'] = $submit_ary['avatar_width'] = $submit_ary['avatar_height'] = 0; + } + else if ($data['width'] && $data['height']) + { + // Only update the dimensions? + if ($config['avatar_max_width'] || $config['avatar_max_height']) + { + if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + + if (!sizeof($error)) + { + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + } + + if (!sizeof($error)) + { + $submit_ary['avatar_width'] = $data['width']; + $submit_ary['avatar_height'] = $data['height']; + } + } + + if ((isset($submit_ary['avatar']) && $submit_ary['avatar'] && (!isset($group_row['group_avatar']))) || $delete) + { + if (isset($group_row['group_avatar']) && $group_row['group_avatar']) + { + avatar_delete('group', $group_row, true); + } + } + + if (!sizeof($error)) + { + // Only set the rank, colour, etc. if it's changed or if we're adding a new + // group. This prevents existing group members being updated if no changes + // were made. + + $group_attributes = array(); + $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients', 'founder_manage'); + foreach ($test_variables as $test) + { + if (isset($submit_ary[$test]) && ($action == 'add' || $group_row['group_' . $test] != $submit_ary[$test])) + { + $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; + } + } + + if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies))) + { + $group_perm_from = request_var('group_perm_from', 0); + + // Copy permissions? + // If the user has the a_authgroups permission and at least one additional permission ability set the permissions are fully transferred. + // We do not limit on one auth category because this can lead to incomplete permissions being tricky to fix for the admin, roles being assigned or added non-default permissions. + // Since the user only has the option to copy permissions from non leader managed groups this seems to be a good compromise. + if ($group_perm_from && $action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) + { + $sql = 'SELECT group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_perm_from; + $result = $db->sql_query($sql); + $check_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Check the group if non-founder + if ($check_row && ($user->data['user_type'] == USER_FOUNDER || $check_row['group_founder_manage'] == 0)) + { + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + // Copy permisisons from/to the acl groups table (only group_id gets changed) + $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_GROUPS_TABLE . ' + WHERE group_id = ' . $group_perm_from; + $result = $db->sql_query($sql); + + $groups_sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups_sql_ary[] = array( + 'group_id' => (int) $group_id, + 'forum_id' => (int) $row['forum_id'], + 'auth_option_id' => (int) $row['auth_option_id'], + 'auth_role_id' => (int) $row['auth_role_id'], + 'auth_setting' => (int) $row['auth_setting'] + ); + } + $db->sql_freeresult($result); + + // Now insert the data + $db->sql_multi_insert(ACL_GROUPS_TABLE, $groups_sql_ary); + + $auth->acl_clear_prefetch(); + } + } + + $cache->destroy('sql', GROUPS_TABLE); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + } + } + + if (sizeof($error)) + { + $group_rank = $submit_ary['rank']; + + $group_desc_data = array( + 'text' => $group_desc, + 'allow_bbcode' => $allow_desc_bbcode, + 'allow_smilies' => $allow_desc_smilies, + 'allow_urls' => $allow_desc_urls + ); + } + } + else if (!$group_id) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc_data = array( + 'text' => '', + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + $group_rank = 0; + $group_type = GROUP_OPEN; + } + else + { + $group_name = $group_row['group_name']; + $group_desc_data = generate_text_for_edit($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_options']); + $group_type = $group_row['group_type']; + $group_rank = $group_row['group_rank']; + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $rank_options = '<option value="0"' . ((!$group_rank) ? ' selected="selected"' : '') . '>' . $user->lang['USER_DEFAULT'] . '</option>'; + + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($group_rank && $row['rank_id'] == $group_rank) ? ' selected="selected"' : ''; + $rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $type_free = ($group_type == GROUP_FREE) ? ' checked="checked"' : ''; + $type_open = ($group_type == GROUP_OPEN) ? ' checked="checked"' : ''; + $type_closed = ($group_type == GROUP_CLOSED) ? ' checked="checked"' : ''; + $type_hidden = ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; + + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . PHPBB_ADMIN_PATH . 'images/no_avatar.gif" alt="" />'; + + $display_gallery = request::is_set_post('display_gallery'); + + if ($config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $back_link = request_var('back_link', ''); + + switch ($back_link) + { + case 'acp_users_groups': + $u_back = append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=users&mode=groups&u=' . request_var('u', 0)); + break; + + default: + $u_back = $this->u_action; + break; + } + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_ADD_GROUP' => ($action == 'add') ? true : false, + 'S_GROUP_PERM' => ($action == 'add' && $auth->acl_get('a_authgroups') && $auth->acl_gets('a_aauth', 'a_fauth', 'a_mauth', 'a_uauth')) ? true : false, + 'S_INCLUDE_SWATCH' => true, + 'S_CAN_UPLOAD' => $can_upload, + 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, + 'S_USER_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_INTERNAL_NAME' => $group_name, + 'GROUP_DESC' => $group_desc_data['text'], + 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', + 'GROUP_FOUNDER_MANAGE' => (isset($group_row['group_founder_manage']) && $group_row['group_founder_manage']) ? ' checked="checked"' : '', + 'GROUP_LEGEND' => (isset($group_row['group_legend']) && $group_row['group_legend']) ? ' checked="checked"' : '', + 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, + 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', + + + 'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'], + 'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'], + 'S_DESC_SMILIES_CHECKED'=> $group_desc_data['allow_smilies'], + + 'S_RANK_OPTIONS' => $rank_options, + 'S_GROUP_OPTIONS' => group_select_options(false, false, (($user->data['user_type'] == USER_FOUNDER) ? false : 0)), + 'AVATAR' => $avatar_img, + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', + 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', + + 'GROUP_TYPE_FREE' => GROUP_FREE, + 'GROUP_TYPE_OPEN' => GROUP_OPEN, + 'GROUP_TYPE_CLOSED' => GROUP_CLOSED, + 'GROUP_TYPE_HIDDEN' => GROUP_HIDDEN, + 'GROUP_TYPE_SPECIAL' => GROUP_SPECIAL, + + 'GROUP_FREE' => $type_free, + 'GROUP_OPEN' => $type_open, + 'GROUP_CLOSED' => $type_closed, + 'GROUP_HIDDEN' => $type_hidden, + + 'U_BACK' => $u_back, + 'U_SWATCH' => append_sid(PHPBB_ADMIN_PATH . 'swatch.' . PHP_EXT, 'form=settings&name=group_colour'), + 'U_ACTION' => "{$this->u_action}&action=$action&g=$group_id", + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024)), + ) + ); + + return; + break; + + case 'list': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = 'GROUP_MEMBERS'; + + // Grab the leaders - always, on every page... + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 1 + ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'U_USER_EDIT' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=users&action=edit&u={$row['user_id']}"), + + 'USERNAME' => $row['username'], + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + // Total number of group members (non-leaders) + $sql = 'SELECT COUNT(user_id) AS total_members + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND group_leader = 0"; + $result = $db->sql_query($sql); + $total_members = (int) $db->sql_fetchfield('total_members'); + $db->sql_freeresult($result); + + $s_action_options = ''; + $options = array('default' => 'DEFAULT', 'approve' => 'APPROVE', 'demote' => 'DEMOTE', 'promote' => 'PROMOTE', 'deleteusers' => 'DELETE'); + + foreach ($options as $option => $lang) + { + $s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>'; + } + + $template->assign_vars(array( + 'S_LIST' => true, + 'S_GROUP_SPECIAL' => ($group_row['group_type'] == GROUP_SPECIAL) ? true : false, + 'S_ACTION_OPTIONS' => $s_action_options, + + 'S_ON_PAGE' => on_page($total_members, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start, true), + 'GROUP_NAME' => ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name'], + + 'U_ACTION' => $this->u_action . "&g=$group_id", + 'U_BACK' => $this->u_action, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=list&field=usernames'), + 'U_DEFAULT_ALL' => "{$this->u_action}&action=default&g=$group_id", + )); + + // Grab the members + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 0 + ORDER BY ug.group_leader DESC, ug.user_pending ASC, u.username_clean"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $pending = false; + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_pending'] && !$pending) + { + $template->assign_block_vars('member', array( + 'S_PENDING' => true) + ); + + $pending = true; + } + + $template->assign_block_vars('member', array( + 'U_USER_EDIT' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=users&action=edit&u={$row['user_id']}"), + + 'USERNAME' => $row['username'], + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + return; + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_GROUP_ADD' => ($auth->acl_get('a_groupadd')) ? true : false) + ); + + // Get us all the groups + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g + ORDER BY g.group_type ASC, g.group_name'; + $result = $db->sql_query($sql); + + $lookup = $cached_group_data = array(); + while ($row = $db->sql_fetchrow($result)) + { + $type = ($row['group_type'] == GROUP_SPECIAL) ? 'special' : 'normal'; + + // used to determine what type a group is + $lookup[$row['group_id']] = $type; + + // used for easy access to the data within a group + $cached_group_data[$type][$row['group_id']] = $row; + $cached_group_data[$type][$row['group_id']]['total_members'] = 0; + } + $db->sql_freeresult($result); + + // How many people are in which group? + $sql = 'SELECT COUNT(ug.user_id) AS total_members, ug.group_id + FROM ' . USER_GROUP_TABLE . ' ug + WHERE ' . $db->sql_in_set('ug.group_id', array_keys($lookup)) . ' + GROUP BY ug.group_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $type = $lookup[$row['group_id']]; + $cached_group_data[$type][$row['group_id']]['total_members'] = $row['total_members']; + } + $db->sql_freeresult($result); + + // The order is... normal, then special + ksort($cached_group_data); + + foreach ($cached_group_data as $type => $row_ary) + { + if ($type == 'special') + { + $template->assign_block_vars('groups', array( + 'S_SPECIAL' => true) + ); + } + + foreach ($row_ary as $group_id => $row) + { + $group_name = (!empty($user->lang['G_' . $row['group_name']]))? $user->lang['G_' . $row['group_name']] : $row['group_name']; + + $template->assign_block_vars('groups', array( + 'U_LIST' => "{$this->u_action}&action=list&g=$group_id", + 'U_EDIT' => "{$this->u_action}&action=edit&g=$group_id", + 'U_DELETE' => ($auth->acl_get('a_groupdel')) ? "{$this->u_action}&action=delete&g=$group_id" : '', + + 'S_GROUP_SPECIAL' => ($row['group_type'] == GROUP_SPECIAL) ? true : false, + + 'GROUP_NAME' => $group_name, + 'TOTAL_MEMBERS' => $row['total_members'], + ) + ); + } + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_icons.php b/phpBB/modules/acp/acp_icons.php new file mode 100644 index 0000000000..6d2c8ad6f1 --- /dev/null +++ b/phpBB/modules/acp/acp_icons.php @@ -0,0 +1,867 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @todo [smilies] check regular expressions for special char replacements (stored specialchared in db) +* @package acp +*/ +class acp_icons +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (request::is_set_post('add')) ? 'add' : $action; + $action = (request::is_set_post('edit')) ? 'edit' : $action; + $action = (request::is_set_post('import')) ? 'import' : $action; + $icon_id = request_var('id', 0); + + $mode = ($mode == 'smilies') ? 'smilies' : 'icons'; + + $this->tpl_name = 'acp_icons'; + + // What are we working on? + switch ($mode) + { + case 'smilies': + $table = SMILIES_TABLE; + $lang = 'SMILIES'; + $fields = 'smiley'; + $img_path = $config['smilies_path']; + break; + + case 'icons': + $table = ICONS_TABLE; + $lang = 'ICONS'; + $fields = 'icons'; + $img_path = $config['icons_path']; + break; + } + + $this->page_title = 'ACP_' . $lang; + + // Clear some arrays + $_images = $_paks = array(); + $notice = ''; + + // Grab file list of paks and images + if ($action == 'edit' || $action == 'add' || $action == 'import') + { + $imglist = filelist(PHPBB_ROOT_PATH . $img_path, ''); + + foreach ($imglist as $path => $img_ary) + { + if (empty($img_ary)) + { + continue; + } + + asort($img_ary, SORT_STRING); + + foreach ($img_ary as $img) + { + $img_size = getimagesize(PHPBB_ROOT_PATH . $img_path . '/' . $path . $img); + + if (!$img_size[0] || !$img_size[1] || strlen($img) > 255) + { + continue; + } + + $_images[$path . $img]['file'] = $path . $img; + $_images[$path . $img]['width'] = $img_size[0]; + $_images[$path . $img]['height'] = $img_size[1]; + } + } + unset($imglist); + + if ($dir = @opendir(PHPBB_ROOT_PATH . $img_path)) + { + while (($file = readdir($dir)) !== false) + { + if (is_file(PHPBB_ROOT_PATH . $img_path . '/' . $file) && preg_match('#\.pak$#i', $file)) + { + $_paks[] = $file; + } + } + closedir($dir); + + if (!empty($_paks)) + { + asort($_paks, SORT_STRING); + } + } + } + + // What shall we do today? Oops, I believe that's trademarked ... + switch ($action) + { + case 'edit': + unset($_images); + $_images = array(); + + // no break; + + case 'add': + + $smilies = $default_row = array(); + $smiley_options = $order_list = $add_order_list = ''; + + if ($action == 'add' && $mode == 'smilies') + { + $sql = 'SELECT * + FROM ' . SMILIES_TABLE . ' + ORDER BY smiley_order'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (empty($smilies[$row['smiley_url']])) + { + $smilies[$row['smiley_url']] = $row; + } + } + $db->sql_freeresult($result); + + if (sizeof($smilies)) + { + foreach ($smilies as $row) + { + $selected = false; + + if (!$smiley_options) + { + $selected = true; + $default_row = $row; + } + $smiley_options .= '<option value="' . $row['smiley_url'] . '"' . (($selected) ? ' selected="selected"' : '') . '>' . $row['smiley_url'] . '</option>'; + + $template->assign_block_vars('smile', array( + 'SMILEY_URL' => addslashes($row['smiley_url']), + 'CODE' => addslashes($row['code']), + 'EMOTION' => addslashes($row['emotion']), + 'WIDTH' => $row['smiley_width'], + 'HEIGHT' => $row['smiley_height'], + 'ORDER' => $row['smiley_order'] + 1, + )); + } + } + } + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order " . (($icon_id || $action == 'add') ? 'DESC' : 'ASC'); + $result = $db->sql_query($sql); + + $data = array(); + $after = false; + $display = 0; + $order_lists = array('', ''); + $add_order_lists = array('', ''); + $display_count = 0; + + while ($row = $db->sql_fetchrow($result)) + { + if ($action == 'add') + { + unset($_images[$row[$fields . '_url']]); + } + + + if ($row[$fields . '_id'] == $icon_id) + { + $after = true; + $display = $row['display_on_posting']; + $data[$row[$fields . '_url']] = $row; + } + else + { + if ($action == 'edit' && !$icon_id) + { + $data[$row[$fields . '_url']] = $row; + } + + $selected = ''; + if (!empty($after)) + { + $selected = ' selected="selected"'; + $after = false; + } + if ($row['display_on_posting']) + { + $display_count++; + } + $after_txt = ($mode == 'smilies') ? $row['code'] : $row['icons_url']; + $order_lists[$row['display_on_posting']] = '<option value="' . ($row[$fields . '_order'] + 1) . '"' . $selected . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . $after_txt) . '</option>' . $order_lists[$row['display_on_posting']]; + + if (!empty($default_row)) + { + $add_order_lists[$row['display_on_posting']] = '<option value="' . ($row[$fields . '_order'] + 1) . '"' . (($row[$fields . '_id'] == $default_row['smiley_id']) ? ' selected="selected"' : '') . '>' . sprintf($user->lang['AFTER_' . $lang], ' -> ' . $after_txt) . '</option>' . $add_order_lists[$row['display_on_posting']]; + } + } + } + $db->sql_freeresult($result); + + $order_list = '<option value="1"' . ((!isset($after)) ? ' selected="selected"' : '') . '>' . $user->lang['FIRST'] . '</option>'; + $add_order_list = '<option value="1">' . $user->lang['FIRST'] . '</option>'; + + if ($action == 'add') + { + $data = $_images; + } + + $colspan = (($mode == 'smilies') ? '7' : '5'); + $colspan += ($icon_id) ? 1 : 0; + $colspan += ($action == 'add') ? 2 : 0; + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_SMILIES' => ($mode == 'smilies') ? true : false, + 'S_ADD' => ($action == 'add') ? true : false, + + 'S_ORDER_LIST_DISPLAY' => $order_list . $order_lists[1], + 'S_ORDER_LIST_UNDISPLAY' => $order_list . $order_lists[0], + 'S_ORDER_LIST_DISPLAY_COUNT' => $display_count + 1, + + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_CONFIG' => $user->lang[$lang . '_CONFIG'], + 'L_URL' => $user->lang[$lang . '_URL'], + 'L_LOCATION' => $user->lang[$lang . '_LOCATION'], + 'L_WIDTH' => $user->lang[$lang . '_WIDTH'], + 'L_HEIGHT' => $user->lang[$lang . '_HEIGHT'], + 'L_ORDER' => $user->lang[$lang . '_ORDER'], + 'L_NO_ICONS' => $user->lang['NO_' . $lang . '_' . strtoupper($action)], + + 'COLSPAN' => $colspan, + 'ID' => $icon_id, + + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=' . (($action == 'add') ? 'create' : 'modify'), + )); + + foreach ($data as $img => $img_row) + { + $template->assign_block_vars('items', array( + 'IMG' => $img, + 'A_IMG' => addslashes($img), + 'IMG_SRC' => PHPBB_ROOT_PATH . $img_path . '/' . $img, + + 'CODE' => ($mode == 'smilies' && isset($img_row['code'])) ? $img_row['code'] : '', + 'EMOTION' => ($mode == 'smilies' && isset($img_row['emotion'])) ? $img_row['emotion'] : '', + + 'S_ID' => (isset($img_row[$fields . '_id'])) ? true : false, + 'ID' => (isset($img_row[$fields . '_id'])) ? $img_row[$fields . '_id'] : 0, + 'WIDTH' => (!empty($img_row[$fields .'_width'])) ? $img_row[$fields .'_width'] : $img_row['width'], + 'HEIGHT' => (!empty($img_row[$fields .'_height'])) ? $img_row[$fields .'_height'] : $img_row['height'], + 'POSTING_CHECKED' => (!empty($img_row['display_on_posting']) || $action == 'add') ? ' checked="checked"' : '', + )); + } + + // Ok, another row for adding an addition code for a pre-existing image... + if ($action == 'add' && $mode == 'smilies' && sizeof($smilies)) + { + $template->assign_vars(array( + 'S_ADD_CODE' => true, + + 'S_IMG_OPTIONS' => $smiley_options, + + 'S_ADD_ORDER_LIST_DISPLAY' => $add_order_list . $add_order_lists[1], + 'S_ADD_ORDER_LIST_UNDISPLAY' => $add_order_list . $add_order_lists[0], + + 'IMG_SRC' => PHPBB_ROOT_PATH . $img_path . '/' . $default_row['smiley_url'], + 'IMG_PATH' => $img_path, + 'PHPBB_ROOT_PATH' => PHPBB_ROOT_PATH, + + 'CODE' => $default_row['code'], + 'EMOTION' => $default_row['emotion'], + + 'WIDTH' => $default_row['smiley_width'], + 'HEIGHT' => $default_row['smiley_height'], + )); + } + + return; + + break; + + case 'create': + case 'modify': + + // Get items to create/modify + $images = array_keys(request::variable('image', array('' => 0), false, request::POST)); + + // Now really get the items + $image_id = request::variable('id', array('' => 0), false, request::POST); + $image_order = request::variable('order', array('' => 0), false, request::POST); + $image_width = request::variable('width', array('' => 0), false, request::POST); + $image_height = request::variable('height', array('' => 0), false, request::POST); + $image_add = request::variable('add_img', array('' => 0), false, request::POST); + $image_display_on_posting = request::variable('display_on_posting', array('' => 0), false, request::POST); + $image_emotion = utf8_normalize_nfc(request_var('emotion', array('' => ''), true)); + $image_code = utf8_normalize_nfc(request_var('code', array('' => ''), true)); + + // Ok, add the relevant bits if we are adding new codes to existing emoticons... + if (request::variable('add_additional_code', false, false, request::POST)) + { + $add_image = request_var('add_image', ''); + $add_code = utf8_normalize_nfc(request_var('add_code', '', true)); + $add_emotion = utf8_normalize_nfc(request_var('add_emotion', '', true)); + + if ($add_image && $add_emotion && $add_code) + { + $images[] = $add_image; + $image_add[$add_image] = true; + + $image_code[$add_image] = $add_code; + $image_emotion[$add_image] = $add_emotion; + $image_width[$add_image] = request_var('add_width', 0); + $image_height[$add_image] = request_var('add_height', 0); + + if (request::variable('add_display_on_posting', false, false, request::POST)) + { + $image_display_on_posting[$add_image] = 1; + } + + $image_order[$add_image] = request_var('add_order', 0); + } + } + + $icons_updated = 0; + $errors = array(); + foreach ($images as $image) + { + if ($mode == 'smilies' && ($image_emotion[$image] == '' || $image_code[$image] == '')) + { + $errors[$image] = 'SMILIE_NO_' . (($image_emotion[$image] == '') ? 'EMOTION' : 'CODE'); + } + else if ($action == 'create' && !isset($image_add[$image])) + { + // skip images where add wasn't checked + } + else + { + if ($image_width[$image] == 0 || $image_height[$image] == 0) + { + $img_size = getimagesize(PHPBB_ROOT_PATH . $img_path . '/' . $image); + $image_width[$image] = $img_size[0]; + $image_height[$image] = $img_size[1]; + } + + $img_sql = array( + $fields . '_url' => $image, + $fields . '_width' => $image_width[$image], + $fields . '_height' => $image_height[$image], + 'display_on_posting' => (isset($image_display_on_posting[$image])) ? 1 : 0, + ); + + if ($mode == 'smilies') + { + $img_sql = array_merge($img_sql, array( + 'emotion' => $image_emotion[$image], + 'code' => $image_code[$image]) + ); + } + + // Image_order holds the 'new' order value + if (!empty($image_order[$image])) + { + $img_sql = array_merge($img_sql, array( + $fields . '_order' => $image_order[$image]) + ); + + // Since we always add 'after' an item, we just need to increase all following + the current by one + $sql = "UPDATE $table + SET {$fields}_order = {$fields}_order + 1 + WHERE {$fields}_order >= {$image_order[$image]}"; + $db->sql_query($sql); + + // If we adjust the order, we need to adjust all other orders too - they became inaccurate... + foreach ($image_order as $_image => $_order) + { + if ($_image == $image) + { + continue; + } + + if ($_order >= $image_order[$image]) + { + $image_order[$_image]++; + } + } + } + + if ($action == 'modify' && !empty($image_id[$image])) + { + $sql = "UPDATE $table + SET " . $db->sql_build_array('UPDATE', $img_sql) . " + WHERE {$fields}_id = " . $image_id[$image]; + $db->sql_query($sql); + $icons_updated++; + } + else if ($action !== 'modify') + { + $sql = "INSERT INTO $table " . $db->sql_build_array('INSERT', $img_sql); + $db->sql_query($sql); + $icons_updated++; + } + + } + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + $level = E_USER_NOTICE; + switch ($icons_updated) + { + case 0: + $suc_lang = "{$lang}_NONE"; + $level = E_USER_WARNING; + break; + + case 1: + $suc_lang = "{$lang}_ONE"; + break; + + default: + $suc_lang = $lang; + } + $errormsgs = ''; + foreach ($errors as $img => $error) + { + $errormsgs .= '<br />' . sprintf($user->lang[$error], $img); + } + if ($action == 'modify') + { + trigger_error($user->lang[$suc_lang . '_EDITED'] . $errormsgs . adm_back_link($this->u_action), $level); + } + else + { + trigger_error($user->lang[$suc_lang . '_ADDED'] . $errormsgs . adm_back_link($this->u_action), $level); + } + + break; + + case 'import': + + $pak = request_var('pak', ''); + $current = request_var('current', ''); + + if ($pak != '') + { + $order = 0; + + if (!($pak_ary = @file(PHPBB_ROOT_PATH . $img_path . '/' . $pak))) + { + trigger_error($user->lang['PAK_FILE_NOT_READABLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Make sure the pak_ary is valid + foreach ($pak_ary as $pak_entry) + { + if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) + { + if ((sizeof($data[1]) != 4 && $mode == 'icons') || + ((sizeof($data[1]) != 6 || (empty($data[1][4]) || empty($data[1][5]))) && $mode == 'smilies' )) + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + + // The user has already selected a smilies_pak file + if ($current == 'delete') + { + if ($db->truncate) + { + $db->sql_query('TRUNCATE TABLE ' . $table); + } + else + { + $db->sql_query('DELETE FROM ' . $table); + } + + switch ($mode) + { + case 'smilies': + break; + + case 'icons': + // Reset all icon_ids + $db->sql_query('UPDATE ' . TOPICS_TABLE . ' SET icon_id = 0'); + $db->sql_query('UPDATE ' . POSTS_TABLE . ' SET icon_id = 0'); + break; + } + } + else + { + $cur_img = array(); + + $field_sql = ($mode == 'smilies') ? 'code' : 'icons_url'; + + $sql = "SELECT $field_sql + FROM $table"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + ++$order; + $cur_img[$row[$field_sql]] = 1; + } + $db->sql_freeresult($result); + } + + foreach ($pak_ary as $pak_entry) + { + $data = array(); + if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data)) + { + if ((sizeof($data[1]) != 4 && $mode == 'icons') || + (sizeof($data[1]) != 6 && $mode == 'smilies')) + { + trigger_error($user->lang['WRONG_PAK_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Stripslash here because it got addslashed before... (on export) + $img = stripslashes($data[1][0]); + $width = stripslashes($data[1][1]); + $height = stripslashes($data[1][2]); + $display_on_posting = stripslashes($data[1][3]); + + if (isset($data[1][4]) && isset($data[1][5])) + { + $emotion = stripslashes($data[1][4]); + $code = stripslashes($data[1][5]); + } + + if ($current == 'replace' && + (($mode == 'smilies' && !empty($cur_img[$code])) || + ($mode == 'icons' && !empty($cur_img[$img])))) + { + $replace_sql = ($mode == 'smilies') ? $code : $img; + $sql = array( + $fields . '_url' => $img, + $fields . '_height' => (int) $height, + $fields . '_width' => (int) $width, + 'display_on_posting' => (int) $display_on_posting, + ); + + if ($mode == 'smilies') + { + $sql = array_merge($sql, array( + 'emotion' => $emotion, + )); + } + + $sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql) . " + WHERE $field_sql = '" . $db->sql_escape($replace_sql) . "'"; + $db->sql_query($sql); + } + else + { + ++$order; + + $sql = array( + $fields . '_url' => $img, + $fields . '_height' => (int) $height, + $fields . '_width' => (int) $width, + $fields . '_order' => (int) $order, + 'display_on_posting'=> (int) $display_on_posting, + ); + + if ($mode == 'smilies') + { + $sql = array_merge($sql, array( + 'code' => $code, + 'emotion' => $emotion, + )); + } + $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql)); + } + } + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + trigger_error($user->lang[$lang . '_IMPORT_SUCCESS'] . adm_back_link($this->u_action)); + } + else + { + $pak_options = ''; + + foreach ($_paks as $pak) + { + $pak_options .= '<option value="' . $pak . '">' . htmlspecialchars($pak) . '</option>'; + } + + $template->assign_vars(array( + 'S_CHOOSE_PAK' => true, + 'S_PAK_OPTIONS' => $pak_options, + + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_NO_PAK_OPTIONS' => $user->lang['NO_' . $lang . '_PAK'], + 'L_CURRENT' => $user->lang['CURRENT_' . $lang], + 'L_CURRENT_EXPLAIN' => $user->lang['CURRENT_' . $lang . '_EXPLAIN'], + 'L_IMPORT_SUBMIT' => $user->lang['IMPORT_' . $lang], + + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . '&action=import', + ) + ); + } + break; + + case 'export': + + $this->page_title = 'EXPORT_' . $lang; + $this->tpl_name = 'message_body'; + + $template->assign_vars(array( + 'MESSAGE_TITLE' => $user->lang['EXPORT_' . $lang], + 'MESSAGE_TEXT' => sprintf($user->lang['EXPORT_' . $lang . '_EXPLAIN'], '<a href="' . $this->u_action . '&action=send">', '</a>'), + + 'S_USER_NOTICE' => true, + ) + ); + + return; + + break; + + case 'send': + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order"; + $result = $db->sql_query($sql); + + $pak = ''; + while ($row = $db->sql_fetchrow($result)) + { + $pak .= "'" . addslashes($row[$fields . '_url']) . "', "; + $pak .= "'" . addslashes($row[$fields . '_width']) . "', "; + $pak .= "'" . addslashes($row[$fields . '_height']) . "', "; + $pak .= "'" . addslashes($row['display_on_posting']) . "', "; + + if ($mode == 'smilies') + { + $pak .= "'" . addslashes($row['emotion']) . "', "; + $pak .= "'" . addslashes($row['code']) . "', "; + } + + $pak .= "\n"; + } + $db->sql_freeresult($result); + + if ($pak != '') + { + garbage_collection(); + + header('Pragma: public'); + + // Send out the Headers + header('Content-Type: text/x-delimtext; name="' . $mode . '.pak"'); + header('Content-Disposition: inline; filename="' . $mode . '.pak"'); + echo $pak; + + flush(); + exit; + } + else + { + trigger_error($user->lang['NO_' . strtoupper($fields) . '_EXPORT'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + break; + + case 'delete': + + if (confirm_box(true)) + { + $sql = "DELETE FROM $table + WHERE {$fields}_id = $icon_id"; + $db->sql_query($sql); + + switch ($mode) + { + case 'smilies': + break; + + case 'icons': + // Reset appropriate icon_ids + $db->sql_query('UPDATE ' . TOPICS_TABLE . " + SET icon_id = 0 + WHERE icon_id = $icon_id"); + + $db->sql_query('UPDATE ' . POSTS_TABLE . " + SET icon_id = 0 + WHERE icon_id = $icon_id"); + break; + } + + $notice = $user->lang[$lang . '_DELETED']; + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'id' => $icon_id, + 'action' => 'delete', + ))); + } + + break; + + case 'move_up': + case 'move_down': + + // Get current order id... + $sql = "SELECT {$fields}_order as current_order + FROM $table + WHERE {$fields}_id = $icon_id"; + $result = $db->sql_query($sql); + $current_order = (int) $db->sql_fetchfield('current_order'); + $db->sql_freeresult($result); + + if ($current_order == 0 && $action == 'move_up') + { + break; + } + + // on move_down, switch position with next order_id... + // on move_up, switch position with previous order_id... + $switch_order_id = ($action == 'move_down') ? $current_order + 1 : $current_order - 1; + + // + $sql = "UPDATE $table + SET {$fields}_order = $current_order + WHERE {$fields}_order = $switch_order_id + AND {$fields}_id <> $icon_id"; + $db->sql_query($sql); + + // Only update the other entry too if the previous entry got updated + if ($db->sql_affectedrows()) + { + $sql = "UPDATE $table + SET {$fields}_order = $switch_order_id + WHERE {$fields}_order = $current_order + AND {$fields}_id = $icon_id"; + $db->sql_query($sql); + } + + $cache->destroy('_icons'); + $cache->destroy('sql', $table); + + break; + } + + // By default, check that image_order is valid and fix it if necessary + $sql = "SELECT {$fields}_id AS order_id, {$fields}_order AS fields_order + FROM $table + ORDER BY display_on_posting DESC, {$fields}_order"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + ++$order; + if ($row['fields_order'] != $order) + { + $db->sql_query("UPDATE $table + SET {$fields}_order = $order + WHERE {$fields}_id = " . $row['order_id']); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['ACP_' . $lang], + 'L_EXPLAIN' => $user->lang['ACP_' . $lang . '_EXPLAIN'], + 'L_IMPORT' => $user->lang['IMPORT_' . $lang], + 'L_EXPORT' => $user->lang['EXPORT_' . $lang], + 'L_NOT_DISPLAYED' => $user->lang[$lang . '_NOT_DISPLAYED'], + 'L_ICON_ADD' => $user->lang['ADD_' . $lang], + 'L_ICON_EDIT' => $user->lang['EDIT_' . $lang], + + 'NOTICE' => $notice, + 'COLSPAN' => ($mode == 'smilies') ? 5 : 3, + + 'S_SMILIES' => ($mode == 'smilies') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_IMPORT' => $this->u_action . '&action=import', + 'U_EXPORT' => $this->u_action . '&action=export', + ) + ); + + $spacer = false; + + $sql = "SELECT * + FROM $table + ORDER BY {$fields}_order ASC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $alt_text = ($mode == 'smilies') ? $row['code'] : ''; + + $template->assign_block_vars('items', array( + 'S_SPACER' => (!$spacer && !$row['display_on_posting']) ? true : false, + 'ALT_TEXT' => $alt_text, + 'IMG_SRC' => PHPBB_ROOT_PATH . $img_path . '/' . $row[$fields . '_url'], + 'WIDTH' => $row[$fields . '_width'], + 'HEIGHT' => $row[$fields . '_height'], + 'CODE' => (isset($row['code'])) ? $row['code'] : '', + 'EMOTION' => (isset($row['emotion'])) ? $row['emotion'] : '', + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row[$fields . '_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row[$fields . '_id'], + 'U_MOVE_UP' => $this->u_action . '&action=move_up&id=' . $row[$fields . '_id'], + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id']) + ); + + if (!$spacer && !$row['display_on_posting']) + { + $spacer = true; + } + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_inactive.php b/phpBB/modules/acp/acp_inactive.php new file mode 100644 index 0000000000..52c7de217f --- /dev/null +++ b/phpBB/modules/acp/acp_inactive.php @@ -0,0 +1,258 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2006 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_inactive +{ + var $u_action; + var $p_master; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $user->add_lang('memberlist'); + + $action = request_var('action', ''); + $mark = request_var('mark', array(0)); + $start = request_var('start', 0); + $submit = request::is_set_post('submit'); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 'i'); + $sort_dir = request_var('sd', 'd'); + + $form_key = 'acp_inactive'; + add_form_key($form_key); + + if ($submit && sizeof($mark)) + { + if ($action !== 'delete' && !check_form_key($form_key)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($action) + { + case 'activate': + case 'delete': + + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark); + $result = $db->sql_query($sql); + + $user_affected = array(); + while ($row = $db->sql_fetchrow($result)) + { + $user_affected[$row['user_id']] = $row['username']; + } + $db->sql_freeresult($result); + + if ($action == 'activate') + { + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Get those 'being activated'... + $sql = 'SELECT user_id, username, user_email, user_lang + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark) . ' + AND user_type = ' . USER_INACTIVE; + $result = $db->sql_query($sql); + + $inactive_users = array(); + while ($row = $db->sql_fetchrow($result)) + { + $inactive_users[] = $row; + } + $db->sql_freeresult($result); + } + + user_active_flip('activate', $mark); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !empty($inactive_users)) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $messenger = new messenger(); + + foreach ($inactive_users as $row) + { + $messenger->template('admin_welcome_activated', $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username'])) + ); + + $messenger->send(NOTIFY_EMAIL); + } + + $messenger->save_queue(); + } + } + else if ($action == 'delete') + { + if (confirm_box(true)) + { + if (!$auth->acl_get('a_userdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + foreach ($mark as $user_id) + { + user_delete('retain', $user_id, $user_affected[$user_id]); + } + + add_log('admin', 'LOG_INACTIVE_' . strtoupper($action), implode(', ', $user_affected)); + } + else + { + $s_hidden_fields = array( + 'mode' => $mode, + 'action' => $action, + 'mark' => $mark, + 'submit' => 1, + 'start' => $start, + ); + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields)); + } + } + + break; + + case 'remind': + if (empty($config['email_enable'])) + { + trigger_error($user->lang['EMAIL_DISABLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type, user_regdate, user_actkey + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $mark); + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + // Send the messages + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $messenger = new messenger(); + $usernames = array(); + + do + { + $messenger->template('user_remind_inactive', $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'REGISTER_DATE' => $user->format_date($row['user_regdate']), + 'U_ACTIVATE' => generate_board_url() . '/ucp.' . PHP_EXT . '?mode=activate&u=' . $row['user_id'] . '&k=' . $row['user_actkey']) + ); + + $messenger->send($row['user_notify_type']); + + $usernames[] = $row['username']; + } + while ($row = $db->sql_fetchrow($result)); + + $messenger->save_queue(); + + add_log('admin', 'LOG_INACTIVE_REMIND', implode(', ', $usernames)); + unset($usernames); + } + $db->sql_freeresult($result); + + break; + } + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('i' => $user->lang['SORT_INACTIVE'], 'j' => $user->lang['SORT_REG_DATE'], 'l' => $user->lang['SORT_LAST_VISIT'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME']); + $sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'r' => 'user_inactive_reason', 'u' => 'username_clean'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + $inactive = array(); + $inactive_count = 0; + + $start = view_inactive_users($inactive, $inactive_count, $config['topics_per_page'], $start, $sql_where, $sql_sort); + + foreach ($inactive as $row) + { + $template->assign_block_vars('inactive', array( + 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']), + 'JOINED' => $user->format_date($row['user_regdate']), + 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']), + 'REASON' => $row['inactive_reason'], + 'USER_ID' => $row['user_id'], + 'USERNAME' => $row['username'], + 'U_USER_ADMIN' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=users&mode=overview&u={$row['user_id']}")) + ); + } + + $option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE'); + if ($config['email_enable']) + { + $option_ary += array('remind' => 'REMIND'); + } + + $template->assign_vars(array( + 'S_INACTIVE_USERS' => true, + 'S_INACTIVE_OPTIONS' => build_select($option_ary), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_ON_PAGE' => on_page($inactive_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $inactive_count, $config['topics_per_page'], $start, true), + + 'U_ACTION' => $this->u_action . '&start=' . $start, + )); + + $this->tpl_name = 'acp_inactive'; + $this->page_title = 'ACP_INACTIVE_USERS'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_jabber.php b/phpBB/modules/acp/acp_jabber.php new file mode 100644 index 0000000000..48ad5c5986 --- /dev/null +++ b/phpBB/modules/acp/acp_jabber.php @@ -0,0 +1,129 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +* @todo Check/enter/update transport info +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_jabber +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $user->add_lang('acp/board'); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_jabber.' . PHP_EXT); + + $action = request_var('action', ''); + $submit = request::is_set_post('submit'); + + if ($mode != 'settings') + { + return; + } + + $this->tpl_name = 'acp_jabber'; + $this->page_title = 'ACP_JABBER_SETTINGS'; + + $jab_enable = request_var('jab_enable', $config['jab_enable']); + $jab_host = request_var('jab_host', $config['jab_host']); + $jab_port = request_var('jab_port', $config['jab_port']); + $jab_username = request_var('jab_username', $config['jab_username']); + $jab_password = request_var('jab_password', $config['jab_password']); + $jab_package_size = request_var('jab_package_size', $config['jab_package_size']); + $jab_use_ssl = request_var('jab_use_ssl', $config['jab_use_ssl']); + + $form_name = 'acp_jabber'; + add_form_key($form_name); + + if ($submit) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $error = array(); + + $message = $user->lang['JAB_SETTINGS_CHANGED']; + $log = 'JAB_SETTINGS_CHANGED'; + + // Is this feature enabled? Then try to establish a connection + if ($jab_enable) + { + $jabber = new jabber($jab_host, $jab_port, $jab_username, $jab_password, $jab_use_ssl); + + if (!$jabber->connect()) + { + trigger_error($user->lang['ERR_JAB_CONNECT'] . '<br /><br />' . $jabber->get_log() . adm_back_link($this->u_action), E_USER_WARNING); + } + + // We'll try to authorise using this account + if (!$jabber->login()) + { + trigger_error($user->lang['ERR_JAB_AUTH'] . '<br /><br />' . $jabber->get_log() . adm_back_link($this->u_action), E_USER_WARNING); + } + + $jabber->disconnect(); + } + else + { + // This feature is disabled. + // We update the user table to be sure all users that have IM as notify type are set to both as notify type + $sql_ary = array( + 'user_notify_type' => NOTIFY_BOTH, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_notify_type = ' . NOTIFY_IM; + $db->sql_query($sql); + } + + set_config('jab_enable', $jab_enable); + set_config('jab_host', $jab_host); + set_config('jab_port', $jab_port); + set_config('jab_username', $jab_username); + set_config('jab_password', $jab_password); + set_config('jab_package_size', $jab_package_size); + set_config('jab_use_ssl', $jab_use_ssl); + + add_log('admin', 'LOG_' . $log); + trigger_error($message . adm_back_link($this->u_action)); + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'JAB_ENABLE' => $jab_enable, + 'L_JAB_SERVER_EXPLAIN' => sprintf($user->lang['JAB_SERVER_EXPLAIN'], '<a href="http://www.jabber.org/">', '</a>'), + 'JAB_HOST' => $jab_host, + 'JAB_PORT' => $jab_port, + 'JAB_USERNAME' => $jab_username, + 'JAB_PASSWORD' => $jab_password, + 'JAB_PACKAGE_SIZE' => $jab_package_size, + 'JAB_USE_SSL' => $jab_use_ssl, + 'S_CAN_USE_SSL' => jabber::can_use_ssl(), + 'S_GTALK_NOTE' => (!@function_exists('dns_get_record')) ? true : false, + )); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_language.php b/phpBB/modules/acp/acp_language.php new file mode 100644 index 0000000000..28de0452d0 --- /dev/null +++ b/phpBB/modules/acp/acp_language.php @@ -0,0 +1,1447 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_language +{ + var $u_action; + var $main_files; + var $language_header = ''; + var $lang_header = ''; + + var $language_file = ''; + var $language_directory = ''; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + global $safe_mode, $file_uploads; + + /** + * @todo make this work with the request class, might require some additional functionality + * inside the request class. Reducing some of the redundance of this code would certainly + * not hurt either. + */ + request::enable_super_globals(); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $this->default_variables(); + + // Check and set some common vars + + $action = (request::is_set_post('update_details')) ? 'update_details' : ''; + $action = (request::is_set_post('download_file')) ? 'download_file' : $action; + $action = (request::is_set_post('upload_file')) ? 'upload_file' : $action; + $action = (request::is_set_post('upload_data')) ? 'upload_data' : $action; + $action = (request::is_set_post('submit_file')) ? 'submit_file' : $action; + $action = (request::is_set_post('remove_store')) ? 'details' : $action; + + $submit = (empty($action) && !request::is_set_post('update') && !request::is_set_post('test_connection')) ? false : true; + $action = (empty($action)) ? request_var('action', '') : $action; + + $form_name = 'acp_lang'; + add_form_key('acp_lang'); + + $lang_id = request_var('id', 0); + if (request::is_set_post('missing_file')) + { + $missing_file = request_var('missing_file', array('' => 0)); + /** + * @todo Do NOT overwrite a request variable. + */ + request::overwrite('language_file', key($missing_file)); + } + + $selected_lang_file = request_var('language_file', '|common.' . PHP_EXT); + + list($this->language_directory, $this->language_file) = explode('|', $selected_lang_file); + + $this->language_directory = basename($this->language_directory); + $this->language_file = basename($this->language_file); + + $user->add_lang('acp/language'); + $this->tpl_name = 'acp_language'; + $this->page_title = 'ACP_LANGUAGE_PACKS'; + + if ($submit && $action == 'upload_data' && request_var('test_connection', '')) + { + $test_connection = false; + $action = 'upload_file'; + $method = request_var('method', ''); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_transfer.' . PHP_EXT); + + switch ($method) + { + case 'ftp': + $transfer = new ftp(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + break; + + case 'ftp_fsock': + $transfer = new ftp_fsock(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + break; + + default: + trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); + break; + } + + $test_connection = $transfer->open_session(); + $transfer->close_session(); + } + + switch ($action) + { + case 'upload_file': + + include_once(PHPBB_ROOT_PATH . 'includes/functions_transfer.' . PHP_EXT); + + $method = request_var('method', ''); + + if (!class_exists($method)) + { + trigger_error('Method does not exist.', E_USER_ERROR); + } + + $requested_data = call_user_func(array($method, 'data')); + foreach ($requested_data as $data => $default) + { + $default_value = request_var($data, ''); + $template->assign_block_vars('data', array( + 'DATA' => $data, + 'NAME' => $user->lang[strtoupper($method . '_' . $data)], + 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], + 'DEFAULT' => (empty($default_value)) ? $default : $default_value + )); + } + + $hidden_data = build_hidden_fields(array( + 'file' => $this->language_file, + 'dir' => $this->language_directory, + 'language_file' => $selected_lang_file, + 'method' => $method) + ); + + /** + * @todo Do not use $_POST here, but request::variable which needs to support more dimensions + */ + $hidden_data .= build_hidden_fields(array('entry' => $_POST['entry']), true, STRIP); + + $template->assign_vars(array( + 'S_UPLOAD' => true, + 'NAME' => $method, + 'U_ACTION' => $this->u_action . "&id=$lang_id&action=upload_data", + 'U_BACK' => $this->u_action . "&id=$lang_id&action=details&language_file=" . urlencode($selected_lang_file), + 'HIDDEN' => $hidden_data, + + 'S_CONNECTION_SUCCESS' => (request_var('test_connection', '') && $test_connection === true) ? true : false, + 'S_CONNECTION_FAILED' => (request_var('test_connection', '') && $test_connection !== true) ? true : false + )); + break; + + case 'update_details': + + if (!$submit || !check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sql_ary = array( + 'lang_english_name' => request_var('lang_english_name', $row['lang_english_name']), + 'lang_local_name' => utf8_normalize_nfc(request_var('lang_local_name', $row['lang_local_name'], true)), + 'lang_author' => utf8_normalize_nfc(request_var('lang_author', $row['lang_author'], true)), + ); + + $db->sql_query('UPDATE ' . LANG_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE lang_id = ' . $lang_id); + + add_log('admin', 'LOG_LANGUAGE_PACK_UPDATED', $sql_ary['lang_english_name']); + + trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action)); + break; + + case 'submit_file': + case 'download_file': + case 'upload_data': + + if (!$submit || !check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_id || empty($_POST['entry'])) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($this->language_directory != 'email' && !is_array($_POST['entry'])) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$this->language_file || (!$this->language_directory && !in_array($this->language_file, $this->main_files))) + { + trigger_error($user->lang['NO_FILE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Before we attempt to write anything let's check if the admin really chose a correct filename + switch ($this->language_directory) + { + case 'email': + // Get email templates + $email_files = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'email', 'txt'); + $email_files = $email_files['email/']; + + if (!in_array($this->language_file, $email_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'acp': + // Get acp files + $acp_files = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'acp', PHP_EXT); + $acp_files = $acp_files['acp/']; + + if (!in_array($this->language_file, $acp_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'mods': + // Get mod files + $mods_files = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'mods', PHP_EXT); + $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); + + if (!in_array($this->language_file, $mods_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + default: + if (!in_array($this->language_file, $this->main_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + } + + if (!$safe_mode) + { + $mkdir_ary = array('language', 'language/' . $row['lang_iso']); + + if ($this->language_directory) + { + $mkdir_ary[] = 'language/' . $row['lang_iso'] . '/' . $this->language_directory; + } + + foreach ($mkdir_ary as $dir) + { + $dir = PHPBB_ROOT_PATH . 'store/' . $dir; + + if (!is_dir($dir)) + { + if (!@mkdir($dir, 0777)) + { + trigger_error("Could not create directory $dir", E_USER_ERROR); + } + @chmod($dir, 0777); + } + } + } + + // Get target filename for storage folder + $filename = $this->get_filename($row['lang_iso'], $this->language_directory, $this->language_file, true, true); + $fp = @fopen(PHPBB_ROOT_PATH . $filename, 'wb'); + + if (!$fp) + { + trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&id=' . $lang_id . '&action=details&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + if ($this->language_directory == 'email') + { + // Email Template + $entry = $this->prepare_lang_entry($_POST['entry'], false); + fwrite($fp, $entry); + } + else + { + $name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file; + $header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header); + + if (strpos($this->language_file, 'help_') === 0) + { + // Help File + $header .= '$help = array(' . "\n"; + fwrite($fp, $header); + + foreach ($_POST['entry'] as $key => $value) + { + if (!is_array($value)) + { + continue; + } + + $entry = "\tarray(\n"; + + foreach ($value as $_key => $_value) + { + $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; + } + + $entry .= "\t),\n"; + fwrite($fp, $entry); + } + + $footer = ");\n\n?>"; + fwrite($fp, $footer); + } + else + { + // Language File + $header .= $this->lang_header; + fwrite($fp, $header); + + foreach ($_POST['entry'] as $key => $value) + { + $entry = $this->format_lang_array($key, $value); + fwrite($fp, $entry); + } + + $footer = "));\n\n?>"; + fwrite($fp, $footer); + } + } + + fclose($fp); + + if ($action == 'download_file') + { + header('Pragma: no-cache'); + header('Content-Type: application/octetstream; name="' . $this->language_file . '"'); + header('Content-disposition: attachment; filename=' . $this->language_file); + + $fp = @fopen(PHPBB_ROOT_PATH . $filename, 'rb'); + while ($buffer = fread($fp, 1024)) + { + echo $buffer; + } + fclose($fp); + + add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); + + exit; + } + else if ($action == 'upload_data') + { + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " + WHERE lang_id = $lang_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $file = request_var('file', ''); + $dir = request_var('dir', ''); + + $selected_lang_file = $dir . '|' . $file; + + $old_file = '/' . $this->get_filename($row['lang_iso'], $dir, $file, false, true); + $lang_path = 'language/' . $row['lang_iso'] . '/' . (($dir) ? $dir . '/' : ''); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_transfer.' . PHP_EXT); + $method = request_var('method', ''); + + if ($method != 'ftp' && $method != 'ftp_fsock') + { + trigger_error($user->lang['INVALID_UPLOAD_METHOD'], E_USER_ERROR); + } + + $transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); + + if (($result = $transfer->open_session()) !== true) + { + trigger_error($user->lang[$result] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + $transfer->rename($lang_path . $file, $lang_path . $file . '.bak'); + $result = $transfer->copy_file('store/' . $lang_path . $file, $lang_path . $file); + + if ($result === false) + { + // If failed, try to rename again and print error out... + $transfer->delete_file($lang_path . $file); + $transfer->rename($lang_path . $file . '.bak', $lang_path . $file); + + trigger_error($user->lang['UPLOAD_FAILED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); + } + + $transfer->close_session(); + + // Remove from storage folder + if (file_exists(PHPBB_ROOT_PATH . 'store/' . $lang_path . $file)) + { + @unlink(PHPBB_ROOT_PATH . 'store/' . $lang_path . $file); + } + + add_log('admin', 'LOG_LANGUAGE_FILE_REPLACED', $file); + + trigger_error($user->lang['UPLOAD_COMPLETED'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id . '&language_file=' . urlencode($selected_lang_file))); + } + + add_log('admin', 'LOG_LANGUAGE_FILE_SUBMITTED', $this->language_file); + $action = 'details'; + + // no break; + + case 'details': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = 'LANGUAGE_PACK_DETAILS'; + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $lang_entries = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $lang_iso = $lang_entries['lang_iso']; + $missing_vars = $missing_files = array(); + + // Get email templates + $email_files = filelist(PHPBB_ROOT_PATH . 'language/' . $config['default_lang'], 'email', 'txt'); + $email_files = $email_files['email/']; + + // Get acp files + $acp_files = filelist(PHPBB_ROOT_PATH . 'language/' . $config['default_lang'], 'acp', PHP_EXT); + $acp_files = $acp_files['acp/']; + + // Get mod files + $mods_files = filelist(PHPBB_ROOT_PATH . 'language/' . $config['default_lang'], 'mods', PHP_EXT); + $mods_files = (isset($mods_files['mods/'])) ? $mods_files['mods/'] : array(); + + // Check if our current filename matches the files + switch ($this->language_directory) + { + case 'email': + if (!in_array($this->language_file, $email_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'acp': + if (!in_array($this->language_file, $acp_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + case 'mods': + if (!in_array($this->language_file, $mods_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + break; + + default: + if (!in_array($this->language_file, $this->main_files)) + { + trigger_error($user->lang['WRONG_LANGUAGE_FILE'] . adm_back_link($this->u_action . '&action=details&id=' . $lang_id), E_USER_WARNING); + } + } + + if (request::is_set_post('remove_store')) + { + $store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true); + + if (file_exists(PHPBB_ROOT_PATH . $store_filename)) + { + @unlink(PHPBB_ROOT_PATH . $store_filename); + } + } + + include_once(PHPBB_ROOT_PATH . 'includes/functions_transfer.' . PHP_EXT); + + $methods = transfer::methods(); + + foreach ($methods as $method) + { + $template->assign_block_vars('buttons', array( + 'VALUE' => $method + )); + } + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'U_ACTION' => $this->u_action . "&action=details&id=$lang_id", + 'U_BACK' => $this->u_action, + 'LANG_LOCAL_NAME' => $lang_entries['lang_local_name'], + 'LANG_ENGLISH_NAME' => $lang_entries['lang_english_name'], + 'LANG_ISO' => $lang_entries['lang_iso'], + 'LANG_AUTHOR' => $lang_entries['lang_author'], + 'ALLOW_UPLOAD' => sizeof($methods) + ) + ); + + // If current lang is different from the default lang, then first try to grab missing/additional vars + if ($lang_iso != $config['default_lang']) + { + $is_missing_var = false; + + foreach ($this->main_files as $file) + { + if (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, '', $file))) + { + $missing_vars[$file] = $this->compare_language_files($config['default_lang'], $lang_iso, '', $file); + + if (sizeof($missing_vars[$file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, '', $file); + } + } + + // Now go through acp/mods directories + foreach ($acp_files as $file) + { + if (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, 'acp', $file))) + { + $missing_vars['acp/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'acp', $file); + + if (sizeof($missing_vars['acp/' . $file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, 'acp', $file); + } + } + + if (sizeof($mods_files)) + { + foreach ($mods_files as $file) + { + if (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, 'mods', $file))) + { + $missing_vars['mods/' . $file] = $this->compare_language_files($config['default_lang'], $lang_iso, 'mods', $file); + + if (sizeof($missing_vars['mods/' . $file])) + { + $is_missing_var = true; + } + } + else + { + $missing_files[] = $this->get_filename($lang_iso, 'mods', $file); + } + } + } + + // More missing files... for example email templates? + foreach ($email_files as $file) + { + if (!file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, 'email', $file))) + { + $missing_files[] = $this->get_filename($lang_iso, 'email', $file); + } + } + + if (sizeof($missing_files)) + { + $template->assign_vars(array( + 'S_MISSING_FILES' => true, + 'L_MISSING_FILES' => sprintf($user->lang['THOSE_MISSING_LANG_FILES'], $lang_entries['lang_local_name']), + 'MISSING_FILES' => implode('<br />', $missing_files)) + ); + } + + if ($is_missing_var) + { + $template->assign_vars(array( + 'S_MISSING_VARS' => true, + 'L_MISSING_VARS_EXPLAIN' => sprintf($user->lang['THOSE_MISSING_LANG_VARIABLES'], $lang_entries['lang_local_name']), + 'U_MISSING_ACTION' => $this->u_action . "&action=$action&id=$lang_id") + ); + + foreach ($missing_vars as $file => $vars) + { + if (!sizeof($vars)) + { + continue; + } + + $template->assign_block_vars('missing', array( + 'FILE' => $file, + 'TPL' => $this->print_language_entries($vars, '', false), + 'KEY' => (strpos($file, '/') === false) ? '|' . $file : str_replace('/', '|', $file)) + ); + } + } + } + + // Main language files + $s_lang_options = '<option value="|common.' . PHP_EXT . '" class="sep">' . $user->lang['LANGUAGE_FILES'] . '</option>'; + foreach ($this->main_files as $file) + { + if (strpos($file, 'help_') === 0) + { + continue; + } + + $prefix = (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; + + $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + + // Help Files + $s_lang_options .= '<option value="|common.' . PHP_EXT . '" class="sep">' . $user->lang['HELP_FILES'] . '</option>'; + foreach ($this->main_files as $file) + { + if (strpos($file, 'help_') !== 0) + { + continue; + } + + $prefix = (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, '', $file, true, true))) ? '* ' : ''; + + $selected = (!$this->language_directory && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + + // Now every other language directory + $check_files = array('email', 'acp', 'mods'); + + foreach ($check_files as $check) + { + if (!sizeof(${$check . '_files'})) + { + continue; + } + + $s_lang_options .= '<option value="|common.' . PHP_EXT . '" class="sep">' . $user->lang[strtoupper($check) . '_FILES'] . '</option>'; + + foreach (${$check . '_files'} as $file) + { + $prefix = (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, $check, $file, true, true))) ? '* ' : ''; + + $selected = ($this->language_directory == $check && $this->language_file == $file) ? ' selected="selected"' : ''; + $s_lang_options .= '<option value="' . $check . '|' . $file . '"' . $selected . '>' . $prefix . $file . '</option>'; + } + } + + // Get Language Entries - if saved within store folder, we take this one (with the option to remove it) + $lang = array(); + + $is_email_file = ($this->language_directory == 'email') ? true : false; + $is_help_file = (strpos($this->language_file, 'help_') === 0) ? true : false; + + $file_from_store = (file_exists(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, true, true))) ? true : false; + $no_store_filename = $this->get_filename($lang_iso, $this->language_directory, $this->language_file); + + if (!$file_from_store && !file_exists(PHPBB_ROOT_PATH . $no_store_filename)) + { + $print_message = sprintf($user->lang['MISSING_LANGUAGE_FILE'], $no_store_filename); + } + else + { + if ($is_email_file) + { + $lang = file_get_contents(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); + } + else + { + $help = array(); + include(PHPBB_ROOT_PATH . $this->get_filename($lang_iso, $this->language_directory, $this->language_file, $file_from_store)); + + if ($is_help_file) + { + $lang = $help; + unset($help); + } + } + + $print_message = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; + } + + // Normal language pack entries + $template->assign_vars(array( + 'U_ENTRY_ACTION' => $this->u_action . "&action=details&id=$lang_id#entries", + 'S_EMAIL_FILE' => $is_email_file, + 'S_FROM_STORE' => $file_from_store, + 'S_LANG_OPTIONS' => $s_lang_options, + 'PRINT_MESSAGE' => $print_message, + ) + ); + + if (!$is_email_file) + { + $tpl = ''; + $name = (($this->language_directory) ? $this->language_directory . '/' : '') . $this->language_file; + + if (isset($missing_vars[$name]) && sizeof($missing_vars[$name])) + { + $tpl .= $this->print_language_entries($missing_vars[$name], '* '); + } + + $tpl .= $this->print_language_entries($lang); + + $template->assign_var('TPL', $tpl); + unset($tpl); + } + else + { + $template->assign_vars(array( + 'LANG' => $lang) + ); + + unset($lang); + } + + return; + + break; + + case 'delete': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row['lang_iso'] == $config['default_lang']) + { + trigger_error($user->lang['NO_REMOVE_DEFAULT_LANG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $db->sql_query('DELETE FROM ' . LANG_TABLE . ' WHERE lang_id = ' . $lang_id); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_lang = '" . $db->sql_escape($config['default_lang']) . "' + WHERE user_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; + $db->sql_query($sql); + + // We also need to remove the translated entries for custom profile fields - we want clean tables, don't we? + $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . ' WHERE lang_id = ' . $lang_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " WHERE image_lang = '" . $db->sql_escape($row['lang_iso']) . "'"; + $result = $db->sql_query($sql); + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_LANGUAGE_PACK_DELETED', $row['lang_english_name']); + + trigger_error(sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']) . adm_back_link($this->u_action)); + break; + + case 'install': + $lang_iso = request_var('iso', ''); + $lang_iso = basename($lang_iso); + + if (!$lang_iso || !file_exists(PHPBB_ROOT_PATH . "language/$lang_iso/iso.txt")) + { + trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file = file(PHPBB_ROOT_PATH . "language/$lang_iso/iso.txt"); + + $lang_pack = array( + 'iso' => $lang_iso, + 'name' => trim(htmlspecialchars($file[0])), + 'local_name'=> trim(htmlspecialchars($file[1], ENT_COMPAT, 'UTF-8')), + 'author' => trim(htmlspecialchars($file[2], ENT_COMPAT, 'UTF-8')) + ); + unset($file); + + $sql = 'SELECT lang_iso + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($lang_iso) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error($user->lang['LANGUAGE_PACK_ALREADY_INSTALLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$lang_pack['name'] || !$lang_pack['local_name']) + { + trigger_error($user->lang['INVALID_LANGUAGE_PACK'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Add language pack + $sql_ary = array( + 'lang_iso' => $lang_pack['iso'], + 'lang_dir' => $lang_pack['iso'], + 'lang_english_name' => $lang_pack['name'], + 'lang_local_name' => $lang_pack['local_name'], + 'lang_author' => $lang_pack['author'] + ); + + $db->sql_query('INSERT INTO ' . LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $lang_id = $db->sql_nextid(); + + $valid_localized = array( + 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', + ); + + $sql_ary = array(); + + $sql = 'SELECT * + FROM ' . STYLES_IMAGESET_TABLE; + $result = $db->sql_query($sql); + while ($imageset_row = $db->sql_fetchrow($result)) + { + if (@file_exists(PHPBB_ROOT_PATH . "styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file(PHPBB_ROOT_PATH . "styles/{$imageset_row['imageset_path']}/imageset/{$lang_pack['iso']}/imageset.cfg"); + foreach ($cfg_data_imageset_data as $image_name => $value) + { + if (strpos($value, '*') !== false) + { + if (substr($value, -1, 1) === '*') + { + list($image_filename, $image_height) = explode('*', $value); + $image_width = 0; + } + else + { + list($image_filename, $image_height, $image_width) = explode('*', $value); + } + } + else + { + $image_filename = $value; + $image_height = $image_width = 0; + } + + if (strpos($image_name, 'img_') === 0 && $image_filename) + { + $image_name = substr($image_name, 4); + if (in_array($image_name, $valid_localized)) + { + $sql_ary[] = array( + 'image_name' => (string) $image_name, + 'image_filename' => (string) $image_filename, + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $imageset_row['imageset_id'], + 'image_lang' => (string) $lang_pack['iso'], + ); + } + } + } + } + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + } + + // Now let's copy the default language entries for custom profile fields for this new language - makes admin's life easier. + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql); + $default_lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + // From the mysql documentation: + // Prior to MySQL 4.0.14, the target table of the INSERT statement cannot appear in the FROM clause of the SELECT part of the query. This limitation is lifted in 4.0.14. + // Due to this we stay on the safe side if we do the insertion "the manual way" + + $sql = 'SELECT field_id, lang_name, lang_explain, lang_default_value + FROM ' . PROFILE_LANG_TABLE . ' + WHERE lang_id = ' . $default_lang_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row['lang_id'] = $lang_id; + $db->sql_query('INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + } + $db->sql_freeresult($result); + + $sql = 'SELECT field_id, option_id, field_type, lang_value + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id = ' . $default_lang_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $row['lang_id'] = $lang_id; + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $row)); + } + $db->sql_freeresult($result); + + add_log('admin', 'LOG_LANGUAGE_PACK_INSTALLED', $lang_pack['name']); + + trigger_error(sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']) . adm_back_link($this->u_action)); + + break; + + case 'download': + + if (!$lang_id) + { + trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + WHERE lang_id = ' . $lang_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $use_method = request_var('use_method', ''); + $methods = array('.tar'); + + $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib'); + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + + $methods[] = $type; + } + + // Let the user decide in which format he wants to have the pack + if (!$use_method) + { + $this->page_title = 'SELECT_DOWNLOAD_FORMAT'; + + $radio_buttons = ''; + foreach ($methods as $method) + { + $radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>'; + } + + $template->assign_vars(array( + 'S_SELECT_METHOD' => true, + 'U_BACK' => $this->u_action, + 'U_ACTION' => $this->u_action . "&action=$action&id=$lang_id", + 'RADIO_BUTTONS' => $radio_buttons) + ); + + return; + } + + if (!in_array($use_method, $methods)) + { + $use_method = '.tar'; + } + + include_once(PHPBB_ROOT_PATH . 'includes/functions_compress.' . PHP_EXT); + + if ($use_method == '.zip') + { + $compress = new compress_zip('w', PHPBB_ROOT_PATH . 'store/lang_' . $row['lang_iso'] . $use_method); + } + else + { + $compress = new compress_tar('w', PHPBB_ROOT_PATH . 'store/lang_' . $row['lang_iso'] . $use_method, $use_method); + } + + // Get email templates + $email_templates = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'email', 'txt'); + $email_templates = $email_templates['email/']; + + // Get acp files + $acp_files = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'acp', PHP_EXT); + $acp_files = $acp_files['acp/']; + + // Get mod files + $mod_files = filelist(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'], 'mods', PHP_EXT); + $mod_files = (isset($mod_files['mods/'])) ? $mod_files['mods/'] : array(); + + // Add main files + $this->add_to_archive($compress, $this->main_files, $row['lang_iso']); + + // Add search files if they exist... + if (file_exists(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'] . '/search_ignore_words.' . PHP_EXT)) + { + $this->add_to_archive($compress, array('search_ignore_words.' . PHP_EXT), $row['lang_iso']); + } + + if (file_exists(PHPBB_ROOT_PATH . 'language/' . $row['lang_iso'] . '/search_synonyms.' . PHP_EXT)) + { + $this->add_to_archive($compress, array('search_synonyms.' . PHP_EXT), $row['lang_iso']); + } + + // Write files in folders + $this->add_to_archive($compress, $email_templates, $row['lang_iso'], 'email'); + $this->add_to_archive($compress, $acp_files, $row['lang_iso'], 'acp'); + $this->add_to_archive($compress, $mod_files, $row['lang_iso'], 'mods'); + + // Write ISO File + $iso_src = htmlspecialchars_decode($row['lang_english_name']) . "\n"; + $iso_src .= htmlspecialchars_decode($row['lang_local_name']) . "\n"; + $iso_src .= htmlspecialchars_decode($row['lang_author']); + $compress->add_data($iso_src, 'language/' . $row['lang_iso'] . '/iso.txt'); + + // index.html files + $compress->add_data('', 'language/' . $row['lang_iso'] . '/index.html'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/email/index.html'); + $compress->add_data('', 'language/' . $row['lang_iso'] . '/acp/index.html'); + + if (sizeof($mod_files)) + { + $compress->add_data('', 'language/' . $row['lang_iso'] . '/mods/index.html'); + } + + $compress->close(); + + $compress->download('lang_' . $row['lang_iso']); + @unlink(PHPBB_ROOT_PATH . 'store/lang_' . $row['lang_iso'] . $use_method); + + exit; + + break; + } + + $sql = 'SELECT user_lang, COUNT(user_lang) AS lang_count + FROM ' . USERS_TABLE . ' + GROUP BY user_lang'; + $result = $db->sql_query($sql); + + $lang_count = array(); + while ($row = $db->sql_fetchrow($result)) + { + $lang_count[$row['user_lang']] = $row['lang_count']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT * + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + $installed = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $installed[] = $row['lang_iso']; + $tagstyle = ($row['lang_iso'] == $config['default_lang']) ? '*' : ''; + + $template->assign_block_vars('lang', array( + 'U_DETAILS' => $this->u_action . "&action=details&id={$row['lang_id']}", + 'U_DOWNLOAD' => $this->u_action . "&action=download&id={$row['lang_id']}", + 'U_DELETE' => $this->u_action . "&action=delete&id={$row['lang_id']}", + + 'ENGLISH_NAME' => $row['lang_english_name'], + 'TAG' => $tagstyle, + 'LOCAL_NAME' => $row['lang_local_name'], + 'ISO' => $row['lang_iso'], + 'USED_BY' => (isset($lang_count[$row['lang_iso']])) ? $lang_count[$row['lang_iso']] : 0, + )); + } + $db->sql_freeresult($result); + + $new_ary = $iso = array(); + $dp = @opendir(PHPBB_ROOT_PATH . 'language'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ($file[0] != '.' && file_exists(PHPBB_ROOT_PATH . "language/$file/iso.txt")) + { + if (!in_array($file, $installed)) + { + if ($iso = file(PHPBB_ROOT_PATH . "language/$file/iso.txt")) + { + if (sizeof($iso) == 3) + { + $new_ary[$file] = array( + 'iso' => $file, + 'name' => trim($iso[0]), + 'local_name'=> trim($iso[1]), + 'author' => trim($iso[2]) + ); + } + } + } + } + } + closedir($dp); + } + + unset($installed); + + if (sizeof($new_ary)) + { + foreach ($new_ary as $iso => $lang_ary) + { + $template->assign_block_vars('notinst', array( + 'ISO' => htmlspecialchars($lang_ary['iso']), + 'LOCAL_NAME' => htmlspecialchars($lang_ary['local_name'], ENT_COMPAT, 'UTF-8'), + 'NAME' => htmlspecialchars($lang_ary['name'], ENT_COMPAT, 'UTF-8'), + 'U_INSTALL' => $this->u_action . '&action=install&iso=' . urlencode($lang_ary['iso'])) + ); + } + } + + unset($new_ary); + } + + + /** + * Set default language variables/header + */ + function default_variables() + { + $this->language_file_header = '<?php +/** +* +* {FILENAME} [{LANG_NAME}] +* +* @package language +* @version $' . 'Id: ' . '$ +* @copyright (c) ' . date('Y') . ' phpBB Group +* @author {CHANGED} - {AUTHOR} +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* DO NOT CHANGE +*/ +if (!defined(\'IN_PHPBB\')) +{ + exit; +} + +if (empty($lang) || !is_array($lang)) +{ + $lang = array(); +} + +// DEVELOPERS PLEASE NOTE +// +// All language files should use UTF-8 as their encoding and the files must not contain a BOM. +// +// Placeholders can now contain order information, e.g. instead of +// \'Page %s of %s\' you can (and should) write \'Page %1$s of %2$s\', this allows +// translators to re-order the output of data while ensuring it remains correct +// +// You do not need this where single placeholders are used, e.g. \'Message %d\' is fine +// equally where a string contains only two placeholders which are used to wrap text +// in a url you again do not need to specify an order e.g., \'Click %sHERE%s\' is fine +'; + + $this->lang_header = ' +$lang = array_merge($lang, array( +'; + + // Language files in language root directory + $this->main_files = array('common.' . PHP_EXT, 'groups.' . PHP_EXT, 'install.' . PHP_EXT, 'mcp.' . PHP_EXT, 'memberlist.' . PHP_EXT, 'posting.' . PHP_EXT, 'search.' . PHP_EXT, 'ucp.' . PHP_EXT, 'viewforum.' . PHP_EXT, 'viewtopic.' . PHP_EXT, 'help_bbcode.' . PHP_EXT, 'help_faq.' . PHP_EXT); + } + + /** + * Get filename/location of language file + */ + function get_filename($lang_iso, $directory, $filename, $check_store = false, $only_return_filename = false) + { + global $safe_mode; + + $check_filename = "language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; + + if ($check_store) + { + $check_store_filename = ($safe_mode) ? "store/langfile_{$lang_iso}" . (($directory) ? '_' . $directory : '') . "_{$filename}" : "store/language/$lang_iso/" . (($directory) ? $directory . '/' : '') . $filename; + + if (!$only_return_filename && file_exists(PHPBB_ROOT_PATH . $check_store_filename)) + { + return $check_store_filename; + } + else if ($only_return_filename) + { + return $check_store_filename; + } + } + + return $check_filename; + } + + /** + * Add files to archive + */ + function add_to_archive(&$compress, $filelist, $lang_iso, $directory = '') + { + foreach ($filelist as $file) + { + // Get source filename + $source = $this->get_filename($lang_iso, $directory, $file, true); + $destination = 'language/' . $lang_iso . '/' . (($directory) ? $directory . '/' : '') . $file; + + // Add file to archive + $compress->add_custom_file(PHPBB_ROOT_PATH . $source, $destination); + } + } + + /** + * Little helper to add some hardcoded template bits + */ + function add_input_field() + { + $keys = func_get_args(); + + $non_static = array_shift($keys); + $value = array_shift($keys); + + if (!$non_static) + { + return '<strong>' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</strong>'; + } + + // If more then 270 characters, then we present a textarea, else an input field + $textarea = (utf8_strlen($value) > 270) ? true : false; + $tpl = ''; + + $tpl .= ($textarea) ? '<textarea name="' : '<input type="text" name="'; + $tpl .= 'entry[' . implode('][', array_map('utf8_htmlspecialchars', $keys)) . ']"'; + + $tpl .= ($textarea) ? ' cols="80" rows="5" class="langvalue">' : ' class="langvalue" value="'; + $tpl .= htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); + $tpl .= ($textarea) ? '</textarea>' : '" />'; + + return $tpl; + } + + /** + * Print language entries + */ + function print_language_entries(&$lang_ary, $key_prefix = '', $input_field = true) + { + $tpl = ''; + + foreach ($lang_ary as $key => $value) + { + if (is_array($value)) + { + // Write key + $tpl .= ' + <tr> + <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> + </tr>'; + + foreach ($value as $_key => $_value) + { + if (is_array($_value)) + { + // Write key + $tpl .= ' + <tr> + <td class="row3" colspan="2">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . ' <strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> + </tr>'; + + foreach ($_value as $__key => $__value) + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($__key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $__value, $key, $_key, $__key); + + $tpl .= '</td> + </tr>'; + } + } + else + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($_key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $_value, $key, $_key); + + $tpl .= '</td> + </tr>'; + } + } + + $tpl .= ' + <tr> + <td class="spacer" colspan="2"> </td> + </tr>'; + } + else + { + // Write key + $tpl .= ' + <tr> + <td class="row1" style="white-space: nowrap;">' . htmlspecialchars($key_prefix, ENT_COMPAT, 'UTF-8') . '<strong>' . htmlspecialchars($key, ENT_COMPAT, 'UTF-8') . '</strong></td> + <td class="row2">'; + + $tpl .= $this->add_input_field($input_field, $value, $key); + + $tpl .= '</td> + </tr>'; + } + } + + return $tpl; + } + + /** + * Compare two language files + */ + function compare_language_files($source_lang, $dest_lang, $directory, $file) + { + $return_ary = array(); + + $lang = array(); + include(PHPBB_ROOT_PATH . "language/{$source_lang}/" . (($directory) ? $directory . '/' : '') . $file); + $lang_entry_src = $lang; + + $lang = array(); + + if (!file_exists(PHPBB_ROOT_PATH . $this->get_filename($dest_lang, $directory, $file, true))) + { + return array(); + } + + include(PHPBB_ROOT_PATH . $this->get_filename($dest_lang, $directory, $file, true)); + + $lang_entry_dst = $lang; + + unset($lang); + + $diff_array_keys = array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst)); + unset($lang_entry_dst); + + foreach ($diff_array_keys as $key) + { + $return_ary[$key] = $lang_entry_src[$key]; + } + + unset($lang_entry_src); + + return $return_ary; + } + + /** + * Return language string value for storage + */ + function prepare_lang_entry($text, $store = true) + { + $text = (STRIP) ? stripslashes($text) : $text; + + // Adjust for storage... + if ($store) + { + $text = str_replace("'", "\\'", str_replace('\\', '\\\\', $text)); + } + + return $text; + } + + /** + * Format language array for storage + */ + function format_lang_array($key, $value, $tabs = "\t") + { + $entry = ''; + + if (!is_array($value)) + { + $entry .= "{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> '" . $this->prepare_lang_entry($value) . "',\n"; + } + else + { + $_tabs = $tabs . "\t"; + $entry .= "\n{$tabs}'" . $this->prepare_lang_entry($key) . "'\t=> array(\n"; + + foreach ($value as $_key => $_value) + { + $entry .= $this->format_lang_array($_key, $_value, $_tabs); + } + + $entry .= "{$tabs}),\n\n"; + } + + return $entry; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_logs.php b/phpBB/modules/acp/acp_logs.php new file mode 100644 index 0000000000..204b2d4935 --- /dev/null +++ b/phpBB/modules/acp/acp_logs.php @@ -0,0 +1,170 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_logs +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('mcp'); + + // Set up general vars + $action = request_var('action', ''); + $forum_id = request_var('f', 0); + $start = request_var('start', 0); + $deletemark = request::variable('delmarked', false, false, request::POST); + $deleteall = request::variable('delall', false, false, request::POST); + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + $this->tpl_name = 'acp_logs'; + $this->log_type = constant('LOG_' . strtoupper($mode)); + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (confirm_box(true)) + { + $where_sql = ''; + + if ($deletemark && sizeof($marked)) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . " + WHERE log_type = {$this->log_type} + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_' . strtoupper($mode)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'f' => $forum_id, + 'start' => $start, + 'delmarked' => $deletemark, + 'delall' => $deleteall, + 'mark' => $marked, + 'st' => $sort_days, + 'sk' => $sort_key, + 'sd' => $sort_dir, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + $l_title = $user->lang['ACP_' . strtoupper($mode) . '_LOGS']; + $l_title_explain = $user->lang['ACP_' . strtoupper($mode) . '_LOGS_EXPLAIN']; + + $this->page_title = $l_title; + + // Define forum list if we're looking @ mod logs + if ($mode == 'mod') + { + $forum_box = '<option value="0">' . $user->lang['ALL_FORUMS'] . '</option>' . make_forum_select($forum_id); + + $template->assign_vars(array( + 'S_SHOW_FORUMS' => true, + 'S_FORUM_BOX' => $forum_box) + ); + } + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort); + + $template->assign_vars(array( + 'L_TITLE' => $l_title, + 'L_EXPLAIN' => $l_title_explain, + 'U_ACTION' => $this->u_action, + + 'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $log_count, $config['topics_per_page'], $start, true), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs'), + ) + ); + + foreach ($log_data as $row) + { + $data = array(); + + $checks = array('viewtopic', 'viewlogs', 'viewforum'); + foreach ($checks as $check) + { + if (isset($row[$check]) && $row[$check]) + { + $data[] = '<a href="' . $row[$check] . '">' . $user->lang['LOGVIEW_' . strtoupper($check)] . '</a>'; + } + } + + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'REPORTEE_USERNAME' => ($row['reportee_username'] && $row['user_id'] != $row['reportee_id']) ? $row['reportee_username_full'] : '', + + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'ID' => $row['id'], + ) + ); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_main.php b/phpBB/modules/acp/acp_main.php new file mode 100644 index 0000000000..c79625ee39 --- /dev/null +++ b/phpBB/modules/acp/acp_main.php @@ -0,0 +1,514 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_main +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + // Show restore permissions notice + if ($user->data['user_perm_from'] && $auth->acl_get('a_switchperm')) + { + $this->tpl_name = 'acp_main'; + $this->page_title = 'ACP_MAIN'; + + $sql = 'SELECT user_id, username, user_colour + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user->data['user_perm_from']; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $perm_from = '<strong' . (($user_row['user_colour']) ? ' style="color: #' . $user_row['user_colour'] . '">' : '>'); + $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '<a href="' . append_sid('memberlist', 'mode=viewprofile&u=' . $user_row['user_id']) . '">' : ''; + $perm_from .= $user_row['username']; + $perm_from .= ($user_row['user_id'] != ANONYMOUS) ? '</a>' : ''; + $perm_from .= '</strong>'; + + $template->assign_vars(array( + 'S_RESTORE_PERMISSIONS' => true, + 'U_RESTORE_PERMISSIONS' => append_sid('ucp', 'mode=restore_perm'), + 'PERM_FROM' => $perm_from, + 'L_PERMISSIONS_TRANSFERRED_EXPLAIN' => sprintf($user->lang['PERMISSIONS_TRANSFERRED_EXPLAIN'], $perm_from, append_sid('ucp', 'mode=restore_perm')), + )); + + return; + } + + $action = request_var('action', ''); + + if ($action) + { + if ($action === 'admlogout') + { + $user->unset_admin(); + $redirect_url = append_sid(PHPBB_ROOT_PATH . 'index.' . PHP_EXT); + meta_refresh(3, $redirect_url); + trigger_error($user->lang['ADM_LOGGED_OUT'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . $redirect_url . '">', '</a>')); + } + + if (!confirm_box(true)) + { + switch ($action) + { + case 'online': + $confirm = true; + $confirm_lang = 'RESET_ONLINE_CONFIRM'; + break; + case 'stats': + $confirm = true; + $confirm_lang = 'RESYNC_STATS_CONFIRM'; + break; + case 'user': + $confirm = true; + $confirm_lang = 'RESYNC_POSTCOUNTS_CONFIRM'; + break; + case 'date': + $confirm = true; + $confirm_lang = 'RESET_DATE_CONFIRM'; + break; + case 'db_track': + $confirm = true; + $confirm_lang = 'RESYNC_POST_MARKING_CONFIRM'; + break; + case 'purge_cache': + $confirm = true; + $confirm_lang = 'PURGE_CACHE_CONFIRM'; + break; + + default: + $confirm = true; + $confirm_lang = 'CONFIRM_OPERATION'; + } + + if ($confirm) + { + confirm_box(false, $user->lang[$confirm_lang], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + ))); + } + } + else + { + switch ($action) + { + + case 'online': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + set_config('record_online_users', 1, true); + set_config('record_online_date', time(), true); + add_log('admin', 'LOG_RESET_ONLINE'); + break; + + case 'stats': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT COUNT(post_id) AS stat + FROM ' . POSTS_TABLE . ' + WHERE post_approved = 1'; + $result = $db->sql_query($sql); + set_config('num_posts', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(topic_id) AS stat + FROM ' . TOPICS_TABLE . ' + WHERE topic_approved = 1'; + $result = $db->sql_query($sql); + set_config('num_topics', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(user_id) AS stat + FROM ' . USERS_TABLE . ' + WHERE user_type IN (' . USER_NORMAL . ',' . USER_FOUNDER . ')'; + $result = $db->sql_query($sql); + set_config('num_users', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT COUNT(attach_id) as stat + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 0'; + $result = $db->sql_query($sql); + set_config('num_files', (int) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + $sql = 'SELECT SUM(filesize) as stat + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 0'; + $result = $db->sql_query($sql); + set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); + $db->sql_freeresult($result); + + if (!function_exists('update_last_username')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + } + update_last_username(); + + add_log('admin', 'LOG_RESYNC_STATS'); + break; + + case 'user': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Resync post counts + $start = $max_post_id = 0; + + // Find the maximum post ID, we can only stop the cycle when we've reached it + $sql = 'SELECT MAX(forum_last_post_id) as max_post_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + + // No maximum post id? :o + if (!$max_post_id) + { + $sql = 'SELECT MAX(post_id) + FROM ' . POSTS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + } + + // Still no maximum post id? Then we are finished + if (!$max_post_id) + { + add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + break; + } + + $step = ($config['num_posts']) ? (max((int) ($config['num_posts'] / 5), 20000)) : 20000; + $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_posts = 0'); + + while ($start < $max_post_id) + { + $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id + FROM ' . POSTS_TABLE . ' + WHERE post_id BETWEEN ' . ($start + 1) . ' AND ' . ($start + $step) . ' + AND post_postcount = 1 AND post_approved = 1 + GROUP BY poster_id'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $sql = 'UPDATE ' . USERS_TABLE . " SET user_posts = user_posts + {$row['num_posts']} WHERE user_id = {$row['poster_id']}"; + $db->sql_query($sql); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $start += $step; + } + + add_log('admin', 'LOG_RESYNC_POSTCOUNTS'); + + break; + + case 'date': + if (!$auth->acl_get('a_board')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + set_config('board_startdate', time() - 1); + add_log('admin', 'LOG_RESET_DATE'); + break; + + case 'db_track': + if ($db->truncate) + { + $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE); + } + else + { + $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); + } + + // This can get really nasty... therefore we only do the last six months + $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60); + + // Select forum ids, do not include categories + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type <> ' . FORUM_CAT; + $result = $db->sql_query($sql); + + $forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = $row['forum_id']; + } + $db->sql_freeresult($result); + + // Any global announcements? ;) + $forum_ids[] = 0; + + // Now go through the forums and get us some topics... + foreach ($forum_ids as $forum_id) + { + $sql = 'SELECT p.poster_id, p.topic_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t + WHERE t.forum_id = ' . $forum_id . ' + AND t.topic_moved_id = 0 + AND t.topic_last_post_time > ' . $get_from_time . ' + AND t.topic_id = p.topic_id + AND p.poster_id <> ' . ANONYMOUS . ' + GROUP BY p.poster_id, p.topic_id'; + $result = $db->sql_query($sql); + + $posted = array(); + while ($row = $db->sql_fetchrow($result)) + { + $posted[$row['poster_id']][] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $sql_ary = array(); + foreach ($posted as $user_id => $topic_row) + { + foreach ($topic_row as $topic_id) + { + $sql_ary[] = array( + 'user_id' => (int) $user_id, + 'topic_id' => (int) $topic_id, + 'topic_posted' => 1, + ); + } + } + unset($posted); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); + } + } + + add_log('admin', 'LOG_RESYNC_POST_MARKING'); + break; + + case 'purge_cache': + if ((int) $user->data['user_type'] !== USER_FOUNDER) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + global $cache; + $cache->purge(); + + // Clear permissions + $auth->acl_clear_prefetch(); + cache_moderators(); + + add_log('admin', 'LOG_PURGE_CACHE'); + break; + } + } + } + + // Get forum statistics + $total_posts = $config['num_posts']; + $total_topics = $config['num_topics']; + $total_users = $config['num_users']; + $total_files = $config['num_files']; + + $start_date = $user->format_date($config['board_startdate']); + + $boarddays = (time() - $config['board_startdate']) / 86400; + + $posts_per_day = sprintf('%.2f', $total_posts / $boarddays); + $topics_per_day = sprintf('%.2f', $total_topics / $boarddays); + $users_per_day = sprintf('%.2f', $total_users / $boarddays); + $files_per_day = sprintf('%.2f', $total_files / $boarddays); + + $upload_dir_size = get_formatted_filesize($config['upload_dir_size']); + + $avatar_dir_size = 0; + + if ($avatar_dir = @opendir(PHPBB_ROOT_PATH . $config['avatar_path'])) + { + while (($file = readdir($avatar_dir)) !== false) + { + if ($file[0] != '.' && $file != 'CVS' && strpos($file, 'index.') === false) + { + $avatar_dir_size += filesize(PHPBB_ROOT_PATH . $config['avatar_path'] . '/' . $file); + } + } + closedir($avatar_dir); + + $avatar_dir_size = get_formatted_filesize($avatar_dir_size); + } + else + { + // Couldn't open Avatar dir. + $avatar_dir_size = $user->lang['NOT_AVAILABLE']; + } + + if ($posts_per_day > $total_posts) + { + $posts_per_day = $total_posts; + } + + if ($topics_per_day > $total_topics) + { + $topics_per_day = $total_topics; + } + + if ($users_per_day > $total_users) + { + $users_per_day = $total_users; + } + + if ($files_per_day > $total_files) + { + $files_per_day = $total_files; + } + + if ($config['allow_attachments'] || $config['allow_pm_attach']) + { + $sql = 'SELECT COUNT(attach_id) AS total_orphan + FROM ' . ATTACHMENTS_TABLE . ' + WHERE is_orphan = 1 + AND filetime < ' . (time() - 3*60*60); + $result = $db->sql_query($sql); + $total_orphan = (int) $db->sql_fetchfield('total_orphan'); + $db->sql_freeresult($result); + } + else + { + $total_orphan = false; + } + + $dbsize = get_database_size(); + + $template->assign_vars(array( + 'TOTAL_POSTS' => $total_posts, + 'POSTS_PER_DAY' => $posts_per_day, + 'TOTAL_TOPICS' => $total_topics, + 'TOPICS_PER_DAY' => $topics_per_day, + 'TOTAL_USERS' => $total_users, + 'USERS_PER_DAY' => $users_per_day, + 'TOTAL_FILES' => $total_files, + 'FILES_PER_DAY' => $files_per_day, + 'START_DATE' => $start_date, + 'AVATAR_DIR_SIZE' => $avatar_dir_size, + 'DBSIZE' => $dbsize, + 'UPLOAD_DIR_SIZE' => $upload_dir_size, + 'TOTAL_ORPHAN' => $total_orphan, + 'S_TOTAL_ORPHAN' => ($total_orphan === false) ? false : true, + 'GZIP_COMPRESSION' => ($config['gzip_compress']) ? $user->lang['ON'] : $user->lang['OFF'], + 'DATABASE_INFO' => $db->sql_server_info(), + 'BOARD_VERSION' => $config['version'], + + 'U_ACTION' => $this->u_action, + 'U_ADMIN_LOG' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=logs&mode=admin'), + 'U_INACTIVE_USERS' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=inactive&mode=list'), + + 'S_ACTION_OPTIONS' => ($auth->acl_get('a_board')) ? true : false, + 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + ) + ); + + $log_data = array(); + $log_count = 0; + + if ($auth->acl_get('a_viewlogs')) + { + view_log('admin', $log_data, $log_count, 5); + + foreach ($log_data as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action']) + ); + } + } + + if ($auth->acl_get('a_user')) + { + $inactive = array(); + $inactive_count = 0; + + view_inactive_users($inactive, $inactive_count, 10); + + foreach ($inactive as $row) + { + $template->assign_block_vars('inactive', array( + 'INACTIVE_DATE' => $user->format_date($row['user_inactive_time']), + 'JOINED' => $user->format_date($row['user_regdate']), + 'LAST_VISIT' => (!$row['user_lastvisit']) ? ' - ' : $user->format_date($row['user_lastvisit']), + 'REASON' => $row['inactive_reason'], + 'USER_ID' => $row['user_id'], + 'USERNAME' => $row['username'], + 'U_USER_ADMIN' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=users&mode=overview&u={$row['user_id']}")) + ); + } + + $option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE'); + if ($config['email_enable']) + { + $option_ary += array('remind' => 'REMIND'); + } + + $template->assign_vars(array( + 'S_INACTIVE_USERS' => true, + 'S_INACTIVE_OPTIONS' => build_select($option_ary)) + ); + } + + // Warn if install is still present + if (file_exists(PHPBB_ROOT_PATH . 'install')) + { + $template->assign_var('S_REMOVE_INSTALL', true); + } + + if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists(PHPBB_ROOT_PATH . 'config.' . PHP_EXT) && is_writable(PHPBB_ROOT_PATH . 'config.' . PHP_EXT)) + { + // World-Writable? (000x) + $template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms(PHPBB_ROOT_PATH . 'config.' . PHP_EXT) & 0x0002)); + } + + $this->tpl_name = 'acp_main'; + $this->page_title = 'ACP_MAIN'; + } +} + +?> diff --git a/phpBB/modules/acp/acp_modules.php b/phpBB/modules/acp/acp_modules.php new file mode 100644 index 0000000000..eb36916344 --- /dev/null +++ b/phpBB/modules/acp/acp_modules.php @@ -0,0 +1,1068 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* - Able to check for new module versions (modes changed/adjusted/added/removed) +* Icons for: +* - module enabled and displayed (common) +* - module enabled and not displayed +* - module deactivated +* - category (enabled) +* - category disabled +*/ + +/** +* @package acp +*/ +class acp_modules +{ + var $module_class = ''; + var $parent_id; + var $u_action; + var $p_master; + + function __construct(p_master $p_master = null) + { + $this->p_master = $p_master; + } + + function main($id, $mode) + { + global $db, $user, $auth, $template, $module, $config; + + // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant) + define('MODULE_INCLUDE', true); + + $user->add_lang('acp/modules'); + $this->tpl_name = 'acp_modules'; + + // module class + $this->module_class = $mode; + + if ($this->module_class == 'ucp') + { + $user->add_lang('ucp'); + } + else if ($this->module_class == 'mcp') + { + $user->add_lang('mcp'); + } + + if ($module->p_class != $this->module_class) + { + $module->add_mod_info($this->module_class); + } + + $this->page_title = strtoupper($this->module_class); + + $this->parent_id = request_var('parent_id', 0); + $module_id = request_var('m', 0); + $action = request_var('action', ''); + $errors = array(); + + switch ($action) + { + case 'delete': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + if (confirm_box(true)) + { + // Make sure we are not directly within a module + if ($module_id == $this->parent_id) + { + $sql = 'SELECT parent_id + FROM ' . MODULES_TABLE . ' + WHERE module_id = ' . $module_id; + $result = $db->sql_query($sql); + $this->parent_id = (int) $db->sql_fetchfield('parent_id'); + $db->sql_freeresult($result); + } + + $errors = $this->delete_module($module_id); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + else + { + confirm_box(false, 'DELETE_MODULE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'parent_id' => $this->parent_id, + 'module_id' => $module_id, + 'action' => $action, + ))); + } + + break; + + case 'enable': + case 'disable': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'UPDATE ' . MODULES_TABLE . ' + SET module_enabled = ' . (($action == 'enable') ? 1 : 0) . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname'])); + $this->remove_cache_file(); + + break; + + case 'move_up': + case 'move_down': + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $move_module_name = $this->move_module_by($row, $action, 1); + + if ($move_module_name !== false) + { + add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name); + $this->remove_cache_file(); + } + + break; + + case 'quickadd': + $quick_install = request_var('quick_install', ''); + + if (confirm_box(true)) + { + if (!$quick_install || strpos($quick_install, '::') === false) + { + break; + } + + list($module_basename, $module_mode) = explode('::', $quick_install); + + // Check if module name and mode exist... + $fileinfo = $this->get_module_infos($module_basename); + $fileinfo = $fileinfo[$module_basename]; + + if (isset($fileinfo['modes'][$module_mode])) + { + $module_data = array( + 'module_basename' => $module_basename, + 'module_enabled' => 0, + 'module_display' => (isset($fileinfo['modes'][$module_mode]['display'])) ? $fileinfo['modes'][$module_mode]['display'] : 1, + 'parent_id' => $this->parent_id, + 'module_class' => $this->module_class, + 'module_langname' => $fileinfo['modes'][$module_mode]['title'], + 'module_mode' => $module_mode, + 'module_auth' => $fileinfo['modes'][$module_mode]['auth'], + ); + + $errors = $this->update_module_data($module_data); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + + trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + } + else + { + confirm_box(false, 'ADD_MODULE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'parent_id' => $this->parent_id, + 'action' => 'quickadd', + 'quick_install' => $quick_install, + ))); + } + + break; + + case 'edit': + + if (!$module_id) + { + trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_row = $this->get_module_row($module_id); + + // no break + + case 'add': + + if ($action == 'add') + { + $module_row = array( + 'module_basename' => '', + 'module_enabled' => 0, + 'module_display' => 1, + 'parent_id' => 0, + 'module_langname' => utf8_normalize_nfc(request_var('module_langname', '', true)), + 'module_mode' => '', + 'module_auth' => '', + ); + } + + $module_data = array(); + + $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']); + $module_data['module_enabled'] = request_var('module_enabled', (int) $module_row['module_enabled']); + $module_data['module_display'] = request_var('module_display', (int) $module_row['module_display']); + $module_data['parent_id'] = request_var('module_parent_id', (int) $module_row['parent_id']); + $module_data['module_class'] = $this->module_class; + $module_data['module_langname'] = utf8_normalize_nfc(request_var('module_langname', (string) $module_row['module_langname'], true)); + $module_data['module_mode'] = request_var('module_mode', (string) $module_row['module_mode']); + + $submit = request::is_set_post('submit'); + + if ($submit) + { + if (!$module_data['module_langname']) + { + trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + $module_type = request_var('module_type', 'category'); + + if ($module_type == 'category') + { + $module_data['module_basename'] = $module_data['module_mode'] = $module_data['module_auth'] = ''; + $module_data['module_display'] = 1; + } + + if ($action == 'edit') + { + $module_data['module_id'] = $module_id; + } + + // Adjust auth row + if ($module_data['module_basename'] && $module_data['module_mode']) + { + $fileinfo = $this->get_module_infos($module_data['module_basename']); + $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth']; + } + + $errors = $this->update_module_data($module_data); + + if (!sizeof($errors)) + { + $this->remove_cache_file(); + + trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id)); + } + } + + // Category/not category? + $is_cat = (!$module_data['module_basename']) ? true : false; + + // Get module information + $module_infos = $this->get_module_infos(); + + // Build name options + $s_name_options = $s_mode_options = ''; + foreach ($module_infos as $option => $values) + { + if (!$module_data['module_basename']) + { + $module_data['module_basename'] = $option; + } + + // Name options + $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>'; + + $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option))); + + // Build module modes + foreach ($values['modes'] as $m_mode => $m_values) + { + if ($option == $module_data['module_basename']) + { + $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>'; + } + + $template->assign_block_vars('m_names.modes', array( + 'OPTION' => $m_mode, + 'VALUE' => $this->lang_name($m_values['title']), + 'A_OPTION' => addslashes($m_mode), + 'A_VALUE' => addslashes($this->lang_name($m_values['title']))) + ); + } + } + + $s_cat_option = '<option value="0"' . (($module_data['parent_id'] == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NO_PARENT'] . '</option>'; + + $template->assign_vars(array_merge(array( + 'S_EDIT_MODULE' => true, + 'S_IS_CAT' => $is_cat, + 'S_CAT_OPTIONS' => $s_cat_option . $this->make_module_select($module_data['parent_id'], ($action == 'edit') ? $module_row['module_id'] : false, false, false, false, true), + 'S_MODULE_NAMES' => $s_name_options, + 'S_MODULE_MODES' => $s_mode_options, + 'U_BACK' => $this->u_action . '&parent_id=' . $this->parent_id, + 'U_EDIT_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + + 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'], + + 'MODULENAME' => $this->lang_name($module_data['module_langname']), + 'ACTION' => $action, + 'MODULE_ID' => $module_id, + + ), + array_change_key_case($module_data, CASE_UPPER)) + ); + + if (sizeof($errors)) + { + $template->assign_vars(array( + 'S_ERROR' => true, + 'ERROR_MSG' => implode('<br />', $errors)) + ); + } + + return; + + break; + } + + // Default management page + if (sizeof($errors)) + { + $template->assign_vars(array( + 'S_ERROR' => true, + 'ERROR_MSG' => implode('<br />', $errors)) + ); + } + + if (!$this->parent_id) + { + $navigation = strtoupper($this->module_class); + } + else + { + $navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>'; + + $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending'); + + foreach ($modules_nav as $row) + { + $langname = $this->lang_name($row['module_langname']); + + if ($row['module_id'] == $this->parent_id) + { + $navigation .= ' -> ' . $langname; + } + else + { + $navigation .= ' -> <a href="' . $this->u_action . '&parent_id=' . $row['module_id'] . '">' . $langname . '</a>'; + } + } + } + + // Jumpbox + $module_box = $this->make_module_select($this->parent_id, false, false, false, false); + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE parent_id = {$this->parent_id} + AND module_class = '" . $db->sql_escape($this->module_class) . "' + ORDER BY left_id"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $langname = $this->lang_name($row['module_langname']); + + if (!$row['module_enabled']) + { + $module_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['DEACTIVATED_MODULE'] .'" />'; + } + else + { + $module_image = (!$row['module_basename'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['MODULE'] . '" />'; + } + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; + + $template->assign_block_vars('modules', array( + 'MODULE_IMAGE' => $module_image, + 'MODULE_TITLE' => $langname, + 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false, + 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false, + + 'S_ACP_CAT_SYSTEM' => ($this->module_class == 'acp' && $row['module_langname'] == 'ACP_CAT_SYSTEM') ? true : false, + 'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false, + + 'U_MODULE' => $this->u_action . '&parent_id=' . $row['module_id'], + 'U_MOVE_UP' => $url . '&action=move_up', + 'U_MOVE_DOWN' => $url . '&action=move_down', + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_ENABLE' => $url . '&action=enable', + 'U_DISABLE' => $url . '&action=disable') + ); + } + while ($row = $db->sql_fetchrow($result)); + } + else if ($this->parent_id) + { + $row = $this->get_module_row($this->parent_id); + + $url = $this->u_action . '&parent_id=' . $this->parent_id . '&m=' . $row['module_id']; + + $template->assign_vars(array( + 'S_NO_MODULES' => true, + 'MODULE_TITLE' => $langname, + 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false, + 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false, + + 'U_EDIT' => $url . '&action=edit', + 'U_DELETE' => $url . '&action=delete', + 'U_ENABLE' => $url . '&action=enable', + 'U_DISABLE' => $url . '&action=disable') + ); + } + $db->sql_freeresult($result); + + // Quick adding module + $module_infos = $this->get_module_infos(); + + // Build quick options + $s_install_options = ''; + foreach ($module_infos as $option => $values) + { + // Name options + $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']">'; + + // Build module modes + foreach ($values['modes'] as $m_mode => $m_values) + { + $s_install_options .= '<option value="' . $option . '::' . $m_mode . '"> ' . $this->lang_name($m_values['title']) . '</option>'; + } + + $s_install_options .= '</optgroup>'; + } + + $template->assign_vars(array( + 'U_SEL_ACTION' => $this->u_action, + 'U_ACTION' => $this->u_action . '&parent_id=' . $this->parent_id, + 'NAVIGATION' => $navigation, + 'MODULE_BOX' => $module_box, + 'PARENT_ID' => $this->parent_id, + 'S_INSTALL_OPTIONS' => $s_install_options, + ) + ); + } + + /** + * Get row for specified module + */ + function get_module_row($module_id) + { + global $db, $user; + + $sql = 'SELECT * + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + return $row; + } + + /** + * Get available module information from module files + */ + function get_module_infos($module = '', $module_class = false) + { + $module_class = ($module_class === false) ? $this->module_class : $module_class; + + $directory = PHPBB_ROOT_PATH . 'includes/' . $module_class . '/info/'; + $fileinfo = array(); + + if (!$module) + { + $dh = @opendir($directory); + + if (!$dh) + { + return $fileinfo; + } + + while (($file = readdir($dh)) !== false) + { + // Is module? + if (preg_match('/^' . $module_class . '_.+\.' . PHP_EXT . '$/', $file)) + { + $class = str_replace('.' . PHP_EXT, '', $file) . '_info'; + + if (!class_exists($class)) + { + include($directory . $file); + } + + // Get module title tag + if (class_exists($class)) + { + $c_class = new $class(); + $module_info = $c_class->module(); + $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; + } + } + } + closedir($dh); + + ksort($fileinfo); + } + else + { + $filename = $module_class . '_' . basename($module); + $class = $module_class . '_' . basename($module) . '_info'; + + if (!class_exists($class)) + { + include($directory . $filename . '.' . PHP_EXT); + } + + // Get module title tag + if (class_exists($class)) + { + $c_class = new $class(); + $module_info = $c_class->module(); + $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info; + } + } + + return $fileinfo; + } + + /** + * Simple version of jumpbox, just lists modules + */ + function make_module_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $ignore_noncat = false) + { + global $db, $user, $auth, $config; + + $sql = 'SELECT module_id, module_enabled, module_basename, parent_id, module_langname, left_id, right_id, module_auth + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + ORDER BY left_id ASC"; + $result = $db->sql_query($sql); + + $right = $iteration = 0; + $padding_store = array('0' => ''); + $module_list = $padding = ''; + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['left_id'] < $right) + { + $padding .= ' '; + $padding_store[$row['parent_id']] = $padding; + } + else if ($row['left_id'] > $right + 1) + { + $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : ''; + } + + $right = $row['right_id']; + + if (!$ignore_acl && $row['module_auth']) + { + // We use zero as the forum id to check - global setting. + if (!$this->p_master->module_auth($row['module_auth'], 0)) + { + continue; + } + } + + // ignore this module? + if ((is_array($ignore_id) && in_array($row['module_id'], $ignore_id)) || $row['module_id'] == $ignore_id) + { + continue; + } + + // empty category + if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) + { + continue; + } + + // ignore non-category? + if ($row['module_basename'] && $ignore_noncat) + { + continue; + } + + $selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : ''); + + $langname = $this->lang_name($row['module_langname']); + $module_list .= '<option value="' . $row['module_id'] . '"' . $selected . ((!$row['module_enabled']) ? ' class="disabled"' : '') . '>' . $padding . $langname . '</option>'; + + $iteration++; + } + $db->sql_freeresult($result); + + unset($padding_store); + + return $module_list; + } + + /** + * Get module branch + */ + function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true) + { + global $db; + + switch ($type) + { + case 'parents': + $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + + case 'children': + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id'; + break; + + default: + $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id'; + break; + } + + $rows = array(); + + $sql = 'SELECT m2.* + FROM ' . MODULES_TABLE . ' m1 + LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition) + WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "' + AND m2.module_class = '" . $db->sql_escape($this->module_class) . "' + AND m1.module_id = $module_id + ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!$include_module && $row['module_id'] == $module_id) + { + continue; + } + + $rows[] = $row; + } + $db->sql_freeresult($result); + + return $rows; + } + + /** + * Remove modules cache file + */ + function remove_cache_file() + { + global $cache; + + // Sanitise for future path use, it's escaped as appropriate for queries + $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class)); + + $cache->destroy('_modules_' . $p_class); + + // Additionally remove sql cache + $cache->destroy('sql', MODULES_TABLE); + } + + /** + * Return correct language name + */ + function lang_name($module_langname) + { + global $user; + + return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname; + } + + /** + * Update/Add module + * + * @param bool $run_inline if set to true errors will be returned and no logs being written + */ + function update_module_data(&$module_data, $run_inline = false) + { + global $db, $user; + + if (!isset($module_data['module_id'])) + { + // no module_id means we're creating a new category/module + if ($module_data['parent_id']) + { + $sql = 'SELECT left_id, right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['parent_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + if ($run_inline) + { + return 'PARENT_NO_EXIST'; + } + + trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING); + } + + // Workaround + $row['left_id'] = (int) $row['left_id']; + $row['right_id'] = (int) $row['right_id']; + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + 2, right_id = right_id + 2 + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND left_id > {$row['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id + 2 + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND {$row['left_id']} BETWEEN left_id AND right_id"; + $db->sql_query($sql); + + $module_data['left_id'] = (int) $row['right_id']; + $module_data['right_id'] = (int) $row['right_id'] + 1; + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $module_data['left_id'] = (int) $row['right_id'] + 1; + $module_data['right_id'] = (int) $row['right_id'] + 2; + } + + $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data); + $db->sql_query($sql); + + $module_data['module_id'] = $db->sql_nextid(); + + if (!$run_inline) + { + add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname'])); + } + } + else + { + $row = $this->get_module_row($module_data['module_id']); + + if ($module_data['module_basename'] && !$row['module_basename']) + { + // we're turning a category into a module + $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false); + + if (sizeof($branch)) + { + return array($user->lang['NO_CATEGORY_TO_MODULE']); + } + } + + if ($row['parent_id'] != $module_data['parent_id']) + { + $this->move_module($module_data['module_id'], $module_data['parent_id']); + } + + $update_ary = $module_data; + unset($update_ary['module_id']); + + $sql = 'UPDATE ' . MODULES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $update_ary) . " + WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "' + AND module_id = " . (int) $module_data['module_id']; + $db->sql_query($sql); + + if (!$run_inline) + { + add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname'])); + } + } + + return array(); + } + + /** + * Move module around the tree + */ + function move_module($from_module_id, $to_parent_id) + { + global $db; + + $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending'); + $from_data = $moved_modules[0]; + $diff = sizeof($moved_modules) * 2; + + $moved_ids = array(); + for ($i = 0; $i < sizeof($moved_modules); ++$i) + { + $moved_ids[] = $moved_modules[$i]['module_id']; + } + + // Resync parents + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id < " . (int) $from_data['right_id'] . ' + AND right_id > ' . (int) $from_data['right_id']; + $db->sql_query($sql); + + // Resync righthand side of tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > " . (int) $from_data['right_id']; + $db->sql_query($sql); + + if ($to_parent_id > 0) + { + $to_data = $this->get_module_row($to_parent_id); + + // Resync new parents + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id + $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id + AND ' . $db->sql_in_set('module_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync the righthand side of the tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + $diff, right_id = right_id + $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > " . (int) $to_data['right_id'] . ' + AND ' . $db->sql_in_set('module_id', $moved_ids, true); + $db->sql_query($sql); + + // Resync moved branch + $to_data['right_id'] += $diff; + if ($to_data['right_id'] > $from_data['right_id']) + { + $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1); + } + else + { + $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1); + } + } + else + { + $sql = 'SELECT MAX(right_id) AS right_id + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . $db->sql_in_set('module_id', $moved_ids, true); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1); + } + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id $diff, right_id = right_id $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND " . $db->sql_in_set('module_id', $moved_ids); + $db->sql_query($sql); + } + + /** + * Remove module from tree + */ + function delete_module($module_id) + { + global $db, $user; + + $row = $this->get_module_row($module_id); + + $branch = $this->get_module_branch($module_id, 'children', 'descending', false); + + if (sizeof($branch)) + { + return array($user->lang['CANNOT_REMOVE_MODULE']); + } + + // If not move + $diff = 2; + $sql = 'DELETE FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND module_id = $module_id"; + $db->sql_query($sql); + + $row['right_id'] = (int) $row['right_id']; + $row['left_id'] = (int) $row['left_id']; + + // Resync tree + $sql = 'UPDATE ' . MODULES_TABLE . " + SET right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id - $diff, right_id = right_id - $diff + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id > {$row['right_id']}"; + $db->sql_query($sql); + + add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname'])); + + return array(); + + } + + /** + * Move module position by $steps up/down + */ + function move_module_by($module_row, $action = 'move_up', $steps = 1) + { + global $db; + + /** + * Fetch all the siblings between the module's current spot + * and where we want to move it to. If there are less than $steps + * siblings between the current spot and the target then the + * module will move as far as possible + */ + $sql = 'SELECT module_id, left_id, right_id, module_langname + FROM ' . MODULES_TABLE . " + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND parent_id = " . (int) $module_row['parent_id'] . ' + AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC'); + $result = $db->sql_query_limit($sql, $steps); + + $target = array(); + while ($row = $db->sql_fetchrow($result)) + { + $target = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($target)) + { + // The module is already on top or bottom + return false; + } + + /** + * $left_id and $right_id define the scope of the nodes that are affected by the move. + * $diff_up and $diff_down are the values to substract or add to each node's left_id + * and right_id in order to move them up or down. + * $move_up_left and $move_up_right define the scope of the nodes that are moving + * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down. + */ + if ($action == 'move_up') + { + $left_id = (int) $target['left_id']; + $right_id = (int) $module_row['right_id']; + + $diff_up = (int) ($module_row['left_id'] - $target['left_id']); + $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + + $move_up_left = (int) $module_row['left_id']; + $move_up_right = (int) $module_row['right_id']; + } + else + { + $left_id = (int) $module_row['left_id']; + $right_id = (int) $target['right_id']; + + $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']); + $diff_down = (int) ($target['right_id'] - $module_row['right_id']); + + $move_up_left = (int) ($module_row['right_id'] + 1); + $move_up_right = (int) $target['right_id']; + } + + // Now do the dirty job + $sql = 'UPDATE ' . MODULES_TABLE . " + SET left_id = left_id + CASE + WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END, + right_id = right_id + CASE + WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up} + ELSE {$diff_down} + END + WHERE module_class = '" . $db->sql_escape($this->module_class) . "' + AND left_id BETWEEN {$left_id} AND {$right_id} + AND right_id BETWEEN {$left_id} AND {$right_id}"; + $db->sql_query($sql); + + $this->remove_cache_file(); + + return $this->lang_name($target['module_langname']); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_permission_roles.php b/phpBB/modules/acp/acp_permission_roles.php new file mode 100644 index 0000000000..0ca445338b --- /dev/null +++ b/phpBB/modules/acp/acp_permission_roles.php @@ -0,0 +1,570 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_permission_roles +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/acp/auth.' . PHP_EXT); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $this->tpl_name = 'acp_permission_roles'; + + $submit = request::is_set_post('submit'); + $role_id = request_var('role_id', 0); + $action = request_var('action', ''); + $action = (request::is_set_post('add')) ? 'add' : $action; + + $form_name = 'acp_permissions'; + add_form_key($form_name); + + switch ($mode) + { + case 'admin_roles': + $permission_type = 'a_'; + $this->page_title = 'ACP_ADMIN_ROLES'; + break; + + case 'user_roles': + $permission_type = 'u_'; + $this->page_title = 'ACP_USER_ROLES'; + break; + + case 'mod_roles': + $permission_type = 'm_'; + $this->page_title = 'ACP_MOD_ROLES'; + break; + + case 'forum_roles': + $permission_type = 'f_'; + $this->page_title = 'ACP_FORUM_ROLES'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN']) + ); + + // Take action... admin submitted something + if ($submit || $action == 'remove') + { + switch ($action) + { + case 'remove': + + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $this->remove_role($role_id, $permission_type); + + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', $role_name); + trigger_error($user->lang['ROLE_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, 'DELETE_ROLE', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'role_id' => $role_id, + 'action' => $action, + ))); + } + + break; + + case 'edit': + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Get role we edit + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // no break; + + case 'add': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $role_name = utf8_normalize_nfc(request_var('role_name', '', true)); + $role_description = utf8_normalize_nfc(request_var('role_description', '', true)); + $auth_settings = request_var('setting', array('' => 0)); + + if (!$role_name) + { + trigger_error($user->lang['NO_ROLE_NAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (utf8_strlen($role_description) > 4000) + { + trigger_error($user->lang['ROLE_DESCRIPTION_LONG'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // if we add/edit a role we check the name to be unique among the settings... + $sql = 'SELECT role_id + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + AND role_name = '" . $db->sql_escape($role_name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Make sure we only print out the error if we add the role or change it's name + if ($row && ($mode == 'add' || ($mode == 'edit' && $role_row['role_name'] != $role_name))) + { + trigger_error(sprintf($user->lang['ROLE_NAME_ALREADY_EXIST'], $role_name) . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'role_name' => (string) $role_name, + 'role_description' => (string) $role_description, + 'role_type' => (string) $permission_type, + ); + + if ($action == 'edit') + { + $sql = 'UPDATE ' . ACL_ROLES_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + } + else + { + // Get maximum role order for inserting a new role... + $sql = 'SELECT MAX(role_order) as max_order + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "'"; + $result = $db->sql_query($sql); + $max_order = (int) $db->sql_fetchfield('max_order'); + $db->sql_freeresult($result); + + $sql_ary['role_order'] = $max_order + 1; + + $sql = 'INSERT INTO ' . ACL_ROLES_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $role_id = $db->sql_nextid(); + } + + // Now add the auth settings + $auth_admin->acl_set_role($role_id, $auth_settings); + + $role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name; + add_log('admin', 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), $role_name); + + trigger_error($user->lang['ROLE_' . strtoupper($action) . '_SUCCESS'] . adm_back_link($this->u_action)); + + break; + } + } + + // Display screens + switch ($action) + { + case 'add': + + $options_from = request_var('options_from', 0); + + $role_row = array( + 'role_name' => utf8_normalize_nfc(request_var('role_name', '', true)), + 'role_description' => utf8_normalize_nfc(request_var('role_description', '', true)), + 'role_type' => $permission_type, + ); + + if ($options_from) + { + $sql = 'SELECT p.auth_option_id, p.auth_setting, o.auth_option + FROM ' . ACL_ROLES_DATA_TABLE . ' p, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = p.auth_option_id + AND p.role_id = ' . $options_from . ' + ORDER BY p.auth_option_id'; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + } + else + { + $sql = 'SELECT auth_option_id, auth_option + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + AND auth_option <> '{$permission_type}' + ORDER BY auth_option_id"; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + } + + // no break; + + case 'edit': + + if ($action == 'edit') + { + if (!$role_id) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $result = $db->sql_query($sql); + $role_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sql = 'SELECT p.auth_option_id, p.auth_setting, o.auth_option + FROM ' . ACL_ROLES_DATA_TABLE . ' p, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = p.auth_option_id + AND p.role_id = ' . $role_id . ' + ORDER BY p.auth_option_id'; + $result = $db->sql_query($sql); + + $auth_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_options[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + } + + if (!$role_row) + { + trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $template->assign_vars(array( + 'S_EDIT' => true, + + 'U_ACTION' => $this->u_action . "&action={$action}&role_id={$role_id}", + 'U_BACK' => $this->u_action, + + 'ROLE_NAME' => $role_row['role_name'], + 'ROLE_DESCRIPTION' => $role_row['role_description'], + 'L_ACL_TYPE' => $user->lang['ACL_TYPE_' . strtoupper($permission_type)], + ) + ); + + // We need to fill the auth options array with ACL_NO options ;) + $sql = 'SELECT auth_option_id, auth_option + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . " + AND auth_option <> '{$permission_type}' + ORDER BY auth_option_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (!isset($auth_options[$row['auth_option']])) + { + $auth_options[$row['auth_option']] = ACL_NO; + } + } + $db->sql_freeresult($result); + + // Unset global permission option + unset($auth_options[$permission_type]); + + // Display auth options + $this->display_auth_options($auth_options); + + // Get users/groups/forums using this preset... + if ($action == 'edit') + { + $hold_ary = $auth_admin->get_role_mask($role_id); + + if (sizeof($hold_ary)) + { + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $template->assign_vars(array( + 'S_DISPLAY_ROLE_MASK' => true, + 'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name)) + ); + + $auth_admin->display_role_mask($hold_ary); + } + } + + return; + break; + + case 'move_up': + case 'move_down': + + $order = request_var('order', 0); + $order_total = $order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . ACL_ROLES_TABLE . ' + SET role_order = ' . $order_total . " - role_order + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + AND role_order IN ($order, " . (($action == 'move_up') ? $order - 1 : $order + 1) . ')'; + $db->sql_query($sql); + + break; + } + + // By default, check that role_order is valid and fix it if necessary + $sql = 'SELECT role_id, role_order + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + $order++; + if ($row['role_order'] != $order) + { + $db->sql_query('UPDATE ' . ACL_ROLES_TABLE . " SET role_order = $order WHERE role_id = {$row['role_id']}"); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + // Display assigned items? + $display_item = request_var('display_item', 0); + + // Select existing roles + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + $s_role_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $role_name = (!empty($user->lang[$row['role_name']])) ? $user->lang[$row['role_name']] : $row['role_name']; + + $template->assign_block_vars('roles', array( + 'ROLE_NAME' => $role_name, + 'ROLE_DESCRIPTION' => (!empty($user->lang[$row['role_description']])) ? $user->lang[$row['role_description']] : nl2br($row['role_description']), + + 'U_EDIT' => $this->u_action . '&action=edit&role_id=' . $row['role_id'], + 'U_REMOVE' => $this->u_action . '&action=remove&role_id=' . $row['role_id'], + 'U_MOVE_UP' => $this->u_action . '&action=move_up&order=' . $row['role_order'], + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&order=' . $row['role_order'], + 'U_DISPLAY_ITEMS' => ($row['role_id'] == $display_item) ? '' : $this->u_action . '&display_item=' . $row['role_id'] . '#assigned_to') + ); + + $s_role_options .= '<option value="' . $row['role_id'] . '">' . $role_name . '</option>'; + + if ($display_item == $row['role_id']) + { + $template->assign_vars(array( + 'L_ROLE_ASSIGNED_TO' => sprintf($user->lang['ROLE_ASSIGNED_TO'], $role_name)) + ); + } + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_ROLE_OPTIONS' => $s_role_options) + ); + + if ($display_item) + { + $template->assign_vars(array( + 'S_DISPLAY_ROLE_MASK' => true) + ); + + $hold_ary = $auth_admin->get_role_mask($display_item); + $auth_admin->display_role_mask($hold_ary); + } + } + + /** + * Display permission settings able to be set + */ + function display_auth_options($auth_options) + { + global $template, $user; + + $content_array = $categories = array(); + $key_sort_array = array(0); + $auth_options = array(0 => $auth_options); + + // Making use of auth_admin method here (we do not really want to change two similar code fragments) + auth_admin::build_permission_array($auth_options, $content_array, $categories, $key_sort_array); + + $content_array = $content_array[0]; + + $template->assign_var('S_NUM_PERM_COLS', sizeof($categories)); + + // Assign to template + foreach ($content_array as $cat => $cat_array) + { + $template->assign_block_vars('auth', array( + 'CAT_NAME' => $user->lang['permission_cat'][$cat], + + 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, + 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, + 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false) + ); + + foreach ($cat_array['permissions'] as $permission => $allowed) + { + $template->assign_block_vars('auth.mask', array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + 'S_NO' => ($allowed == ACL_NO) ? true : false, + + 'FIELD_NAME' => $permission, + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + } + } + + /** + * Remove role + */ + function remove_role($role_id, $permission_type) + { + global $db; + + $auth_admin = new auth_admin(); + + // Get complete auth array + $sql = 'SELECT auth_option, auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + $auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + $auth_settings[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + + // Get the role auth settings we need to re-set... + $sql = 'SELECT o.auth_option, r.auth_setting + FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = r.auth_option_id + AND r.role_id = ' . $role_id; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $auth_settings[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // Get role assignments + $hold_ary = $auth_admin->get_role_mask($role_id); + + // Re-assign permissions + foreach ($hold_ary as $forum_id => $forum_ary) + { + if (isset($forum_ary['users'])) + { + $auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false); + } + + if (isset($forum_ary['groups'])) + { + $auth_admin->acl_set('group', $forum_id, $forum_ary['groups'], $auth_settings, 0, false); + } + } + + // Remove role from users and groups just to be sure (happens through acl_set) + $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' + WHERE auth_role_id = ' . $role_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' + WHERE auth_role_id = ' . $role_id; + $db->sql_query($sql); + + // Remove role data and role + $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + $sql = 'DELETE FROM ' . ACL_ROLES_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + $auth_admin->acl_clear_prefetch(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_permissions.php b/phpBB/modules/acp/acp_permissions.php new file mode 100644 index 0000000000..3512824d0c --- /dev/null +++ b/phpBB/modules/acp/acp_permissions.php @@ -0,0 +1,1195 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_permissions +{ + var $u_action; + var $permission_dropdown; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/acp/auth.' . PHP_EXT); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $this->tpl_name = 'acp_permissions'; + + // Trace has other vars + if ($mode == 'trace') + { + $user_id = request_var('u', 0); + $forum_id = request_var('f', 0); + $permission = request_var('auth', ''); + + $this->tpl_name = 'permission_trace'; + + if ($user_id && isset($auth_admin->acl_options['id'][$permission]) && $auth->acl_get('a_viewauth')) + { + $this->page_title = sprintf($user->lang['TRACE_PERMISSION'], $user->lang['acl_' . $permission]['lang']); + $this->permission_trace($user_id, $forum_id, $permission); + return; + } + trigger_error('NO_MODE', E_USER_ERROR); + } + + // Set some vars + $action = request_var('action', array('' => 0)); + $action = key($action); + $action = (request::is_set_post('psubmit')) ? 'apply_permissions' : $action; + + $all_forums = request_var('all_forums', 0); + $subforum_id = request_var('subforum_id', 0); + $forum_id = request_var('forum_id', array(0)); + + $username = request_var('username', array(''), true); + $usernames = request_var('usernames', '', true); + $user_id = request_var('user_id', array(0)); + + $group_id = request_var('group_id', array(0)); + $select_all_groups = request_var('select_all_groups', 0); + + $form_name = 'acp_permissions'; + add_form_key($form_name); + + // If select all groups is set, we pre-build the group id array (this option is used for other screens to link to the permission settings screen) + if ($select_all_groups) + { + // Add default groups to selection + $sql_and = (!$config['coppa_enable']) ? " AND group_name <> 'REGISTERED_COPPA'" : ''; + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . ' + WHERE group_type = ' . GROUP_SPECIAL . " + $sql_and"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $group_id[] = $row['group_id']; + } + $db->sql_freeresult($result); + } + + // Map usernames to ids and vice versa + if ($usernames) + { + $username = explode("\n", $usernames); + } + unset($usernames); + + if (sizeof($username) && !sizeof($user_id)) + { + user_get_id_name($user_id, $username); + + if (!sizeof($user_id)) + { + trigger_error($user->lang['SELECTED_USER_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + unset($username); + + // Build forum ids (of all forums are checked or subforum listing used) + if ($all_forums) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + $forum_id = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id[] = (int) $row['forum_id']; + } + $db->sql_freeresult($result); + } + else if ($subforum_id) + { + $forum_id = array(); + foreach (get_forum_branch($subforum_id, 'children') as $row) + { + $forum_id[] = (int) $row['forum_id']; + } + } + + // Define some common variables for every mode + $error = array(); + + $permission_scope = (strpos($mode, '_global') !== false) ? 'global' : 'local'; + + // Showing introductionary page? + if ($mode == 'intro') + { + $this->page_title = 'ACP_PERMISSIONS'; + + $template->assign_vars(array( + 'S_INTRO' => true) + ); + + return; + } + + switch ($mode) + { + case 'setting_user_global': + case 'setting_group_global': + $this->permission_dropdown = array('u_', 'm_', 'a_'); + $permission_victim = ($mode == 'setting_user_global') ? array('user') : array('group'); + $this->page_title = ($mode == 'setting_user_global') ? 'ACP_USERS_PERMISSIONS' : 'ACP_GROUPS_PERMISSIONS'; + break; + + case 'setting_user_local': + case 'setting_group_local': + $this->permission_dropdown = array('f_', 'm_'); + $permission_victim = ($mode == 'setting_user_local') ? array('user', 'forums') : array('group', 'forums'); + $this->page_title = ($mode == 'setting_user_local') ? 'ACP_USERS_FORUM_PERMISSIONS' : 'ACP_GROUPS_FORUM_PERMISSIONS'; + break; + + case 'setting_admin_global': + case 'setting_mod_global': + $this->permission_dropdown = (strpos($mode, '_admin_') !== false) ? array('a_') : array('m_'); + $permission_victim = array('usergroup'); + $this->page_title = ($mode == 'setting_admin_global') ? 'ACP_ADMINISTRATORS' : 'ACP_GLOBAL_MODERATORS'; + break; + + case 'setting_mod_local': + case 'setting_forum_local': + $this->permission_dropdown = ($mode == 'setting_mod_local') ? array('m_') : array('f_'); + $permission_victim = array('forums', 'usergroup'); + $this->page_title = ($mode == 'setting_mod_local') ? 'ACP_FORUM_MODERATORS' : 'ACP_FORUM_PERMISSIONS'; + break; + + case 'view_admin_global': + case 'view_user_global': + case 'view_mod_global': + $this->permission_dropdown = ($mode == 'view_admin_global') ? array('a_') : (($mode == 'view_user_global') ? array('u_') : array('m_')); + $permission_victim = array('usergroup_view'); + $this->page_title = ($mode == 'view_admin_global') ? 'ACP_VIEW_ADMIN_PERMISSIONS' : (($mode == 'view_user_global') ? 'ACP_VIEW_USER_PERMISSIONS' : 'ACP_VIEW_GLOBAL_MOD_PERMISSIONS'); + break; + + case 'view_mod_local': + case 'view_forum_local': + $this->permission_dropdown = ($mode == 'view_mod_local') ? array('m_') : array('f_'); + $permission_victim = array('forums', 'usergroup_view'); + $this->page_title = ($mode == 'view_mod_local') ? 'ACP_VIEW_FORUM_MOD_PERMISSIONS' : 'ACP_VIEW_FORUM_PERMISSIONS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN']) + ); + + // Get permission type + $permission_type = request_var('type', $this->permission_dropdown[0]); + + if (!in_array($permission_type, $this->permission_dropdown)) + { + trigger_error($user->lang['WRONG_PERMISSION_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + + // Handle actions + if (strpos($mode, 'setting_') === 0 && $action) + { + switch ($action) + { + case 'delete': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + // All users/groups selected? + $all_users = request::is_set_post('all_users'); + $all_groups = request::is_set_post('all_groups'); + + if ($all_users || $all_groups) + { + $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); + + if ($all_users && sizeof($items['user_ids'])) + { + $user_id = $items['user_ids']; + } + else if ($all_groups && sizeof($items['group_ids'])) + { + $group_id = $items['group_ids']; + } + } + + if (sizeof($user_id) || sizeof($group_id)) + { + $this->remove_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id, $forum_id); + } + else + { + trigger_error($user->lang['NO_USER_GROUP_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + break; + + case 'apply_permissions': + if (!request::is_set_post('setting')) + { + trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->set_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id); + break; + + case 'apply_all_permissions': + if (!request::is_set_post('setting')) + { + trigger_error($user->lang['NO_AUTH_SETTING_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->set_all_permissions($mode, $permission_type, $auth_admin, $user_id, $group_id); + break; + } + } + + + // Setting permissions screen + $s_hidden_fields = build_hidden_fields(array( + 'user_id' => $user_id, + 'group_id' => $group_id, + 'forum_id' => $forum_id, + 'type' => $permission_type) + ); + + // Go through the screens/options needed and present them in correct order + foreach ($permission_victim as $victim) + { + switch ($victim) + { + case 'forum_dropdown': + + if (sizeof($forum_id)) + { + $this->check_existence('forum', $forum_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => make_forum_select(false, false, true, false, false)) + ); + + break; + + case 'forums': + + if (sizeof($forum_id)) + { + $this->check_existence('forum', $forum_id); + continue 2; + } + + $forum_list = make_forum_select(false, false, true, false, false, false, true); + + // Build forum options + $s_forum_options = ''; + foreach ($forum_list as $f_id => $f_row) + { + $s_forum_options .= '<option value="' . $f_id . '"' . (($f_row['selected']) ? ' selected="selected"' : '') . (($f_row['disabled']) ? ' disabled="disabled" class="disabled-option"' : '') . '>' . $f_row['padding'] . $f_row['forum_name'] . '</option>'; + } + + // Build subforum options + $s_subforum_options = $this->build_subforum_options($forum_list); + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => $s_forum_options, + 'S_SUBFORUM_OPTIONS' => $s_subforum_options, + 'S_FORUM_ALL' => true, + 'S_FORUM_MULTIPLE' => true) + ); + + break; + + case 'user': + + if (sizeof($user_id)) + { + $this->check_existence('user', $user_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_USER' => true, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=select_victim&field=username&select_single=true'), + )); + + break; + + case 'group': + + if (sizeof($group_id)) + { + $this->check_existence('group', $group_id); + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_GROUP' => true, + 'S_GROUP_OPTIONS' => group_select_options(false, false, (($user->data['user_type'] == USER_FOUNDER) ? false : 0))) + ); + + break; + + case 'usergroup': + case 'usergroup_view': + + $all_users = request::is_set_post('all_users'); + $all_groups = request::is_set_post('all_groups'); + + if ((sizeof($user_id) && !$all_users) || (sizeof($group_id) && !$all_groups)) + { + if (sizeof($user_id)) + { + $this->check_existence('user', $user_id); + } + + if (sizeof($group_id)) + { + $this->check_existence('group', $group_id); + } + + continue 2; + } + + // Now we check the users... because the "all"-selection is different here (all defined users/groups) + $items = $this->retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type); + + if ($all_users && sizeof($items['user_ids'])) + { + $user_id = $items['user_ids']; + continue 2; + } + + if ($all_groups && sizeof($items['group_ids'])) + { + $group_id = $items['group_ids']; + continue 2; + } + + $template->assign_vars(array( + 'S_SELECT_USERGROUP' => ($victim == 'usergroup') ? true : false, + 'S_SELECT_USERGROUP_VIEW' => ($victim == 'usergroup_view') ? true : false, + 'S_DEFINED_USER_OPTIONS' => $items['user_ids_options'], + 'S_DEFINED_GROUP_OPTIONS' => $items['group_ids_options'], + 'S_ADD_GROUP_OPTIONS' => group_select_options(false, $items['group_ids'], (($user->data['user_type'] == USER_FOUNDER) ? false : 0)), + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=add_user&field=username&select_single=true'), + )); + + break; + } + + // The S_ALLOW_SELECT parameter below is a measure to lower memory usage. + // If there are more than 5 forums selected the admin is not able to select all users/groups too. + // We need to see if the number of forums can be increased or need to be decreased. + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'ANONYMOUS_USER_ID' => ANONYMOUS, + + 'S_SELECT_VICTIM' => true, + 'S_ALLOW_ALL_SELECT' => (sizeof($forum_id) > 5) ? false : true, + 'S_CAN_SELECT_USER' => ($auth->acl_get('a_authusers')) ? true : false, + 'S_CAN_SELECT_GROUP' => ($auth->acl_get('a_authgroups')) ? true : false, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + // Let the forum names being displayed + if (sizeof($forum_id)) + { + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id) . ' + ORDER BY left_id ASC'; + $result = $db->sql_query($sql); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_FORUM_NAMES' => (sizeof($forum_names)) ? true : false, + 'FORUM_NAMES' => implode(', ', $forum_names)) + ); + } + + return; + } + + // Do not allow forum_ids being set and no other setting defined (will bog down the server too much) + if (sizeof($forum_id) && !sizeof($user_id) && !sizeof($group_id)) + { + trigger_error($user->lang['ONLY_FORUM_DEFINED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $template->assign_vars(array( + 'S_PERMISSION_DROPDOWN' => (sizeof($this->permission_dropdown) > 1) ? $this->build_permission_dropdown($this->permission_dropdown, $permission_type, $permission_scope) : false, + 'L_PERMISSION_TYPE' => $user->lang['ACL_TYPE_' . strtoupper($permission_type)], + + 'U_ACTION' => $this->u_action, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + if (strpos($mode, 'setting_') === 0) + { + $template->assign_vars(array( + 'S_SETTING_PERMISSIONS' => true) + ); + + $hold_ary = $auth_admin->get_mask('set', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NO); + $auth_admin->display_mask('set', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + } + else + { + $template->assign_vars(array( + 'S_VIEWING_PERMISSIONS' => true) + ); + + $hold_ary = $auth_admin->get_mask('view', (sizeof($user_id)) ? $user_id : false, (sizeof($group_id)) ? $group_id : false, (sizeof($forum_id)) ? $forum_id : false, $permission_type, $permission_scope, ACL_NEVER); + $auth_admin->display_mask('view', $permission_type, $hold_ary, ((sizeof($user_id)) ? 'user' : 'group'), (($permission_scope == 'local') ? true : false)); + } + } + + /** + * Build +subforum options + */ + function build_subforum_options($forum_list) + { + global $user; + + $s_options = ''; + + $forum_list = array_merge($forum_list); + + foreach ($forum_list as $key => $row) + { + if ($row['disabled']) + { + continue; + } + + $s_options .= '<option value="' . $row['forum_id'] . '"' . (($row['selected']) ? ' selected="selected"' : '') . '>' . $row['padding'] . $row['forum_name']; + + // We check if a branch is there... + $branch_there = false; + + foreach (array_slice($forum_list, $key + 1) as $temp_row) + { + if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) + { + $branch_there = true; + break; + } + continue; + } + + if ($branch_there) + { + $s_options .= ' [' . $user->lang['PLUS_SUBFORUMS'] . ']'; + } + + $s_options .= '</option>'; + } + + return $s_options; + } + + /** + * Build dropdown field for changing permission types + */ + function build_permission_dropdown($options, $default_option, $permission_scope) + { + global $user, $auth; + + $s_dropdown_options = ''; + foreach ($options as $setting) + { + if (!$auth->acl_get('a_' . str_replace('_', '', $setting) . 'auth')) + { + continue; + } + + $selected = ($setting == $default_option) ? ' selected="selected"' : ''; + $l_setting = (isset($user->lang['permission_type'][$permission_scope][$setting])) ? $user->lang['permission_type'][$permission_scope][$setting] : $user->lang['permission_type'][$setting]; + $s_dropdown_options .= '<option value="' . $setting . '"' . $selected . '>' . $l_setting . '</option>'; + } + + return $s_dropdown_options; + } + + /** + * Check if selected items exist. Remove not found ids and if empty return error. + */ + function check_existence($mode, &$ids) + { + global $db, $user; + + switch ($mode) + { + case 'user': + $table = USERS_TABLE; + $sql_id = 'user_id'; + break; + + case 'group': + $table = GROUPS_TABLE; + $sql_id = 'group_id'; + break; + + case 'forum': + $table = FORUMS_TABLE; + $sql_id = 'forum_id'; + break; + } + + if (sizeof($ids)) + { + $sql = "SELECT $sql_id + FROM $table + WHERE " . $db->sql_in_set($sql_id, $ids); + $result = $db->sql_query($sql); + + $ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = (int) $row[$sql_id]; + } + $db->sql_freeresult($result); + } + + if (!sizeof($ids)) + { + trigger_error($user->lang['SELECTED_' . strtoupper($mode) . '_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + /** + * Apply permissions + */ + function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + { + global $user, $auth; + + $psubmit = request_var('psubmit', array(0 => array(0 => 0))); + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $ug_id = $forum_id = 0; + + // We loop through the auth settings defined in our submit + list($ug_id, ) = each($psubmit); + list($forum_id, ) = each($psubmit[$ug_id]); + + $auth_settings = request::variable('setting', array(0 => array(0 => array('' => 0))), false, request::POST); + if (!isset($auth_settings[$ug_id][$forum_id]) || !sizeof($auth_settings[$ug_id][$forum_id]))) + { + trigger_error('WRONG_PERMISSION_SETTING_FORMAT', E_USER_WARNING); + } + + // Do we have a role we want to set? + $assigned_role = request::variable(array('role', $ug_id, $forum_id), 0, false, request::POST)); + + // Do the admin want to set these permissions to other items too? + $inherit = request_var('inherit', array(0 => array(0))); + + $ug_id = array($ug_id); + $forum_id = array($forum_id); + + if (sizeof($inherit)) + { + foreach ($inherit as $_ug_id => $forum_id_ary) + { + // Inherit users/groups? + if (!in_array($_ug_id, $ug_id)) + { + $ug_id[] = $_ug_id; + } + + // Inherit forums? + $forum_id = array_merge($forum_id, array_keys($forum_id_ary)); + } + } + + $forum_id = array_unique($forum_id); + + // If the auth settings differ from the assigned role, then do not set a role... + if ($assigned_role) + { + if (!$this->check_assigned_role($assigned_role, $auth_settings)) + { + $assigned_role = 0; + } + } + + // Update the permission set... + $auth_admin->acl_set($ug_type, $forum_id, $ug_id, $auth_settings, $assigned_role); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + // Remove users who are now moderators or admins from everyones foes list + if ($permission_type == 'm_' || $permission_type == 'a_') + { + update_foes($group_id, $user_id); + } + + $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_id, $forum_id); + + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + + /** + * Apply all permissions + */ + function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) + { + global $user, $auth; + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $auth_settings = request::variable('setting', array(0 => array(0 => array('' => 0))), false, request::POST); + $auth_roles = request::variable('role', array(0 => array(0 => 0)), false, request::POST); + $ug_ids = $forum_ids = array(); + + // We need to go through the auth settings + foreach ($auth_settings as $ug_id => $forum_auth_row) + { + $ug_ids[] = $ug_id; + + foreach ($forum_auth_row as $forum_id => $auth_options) + { + $forum_ids[] = $forum_id; + + // Check role... + $assigned_role = (isset($auth_roles[$ug_id][$forum_id])) ? $auth_roles[$ug_id][$forum_id] : 0; + + // If the auth settings differ from the assigned role, then do not set a role... + if ($assigned_role) + { + if (!$this->check_assigned_role($assigned_role, $auth_options)) + { + $assigned_role = 0; + } + } + + // Update the permission set... + $auth_admin->acl_set($ug_type, $forum_id, $ug_id, $auth_options, $assigned_role, false); + } + } + + $auth_admin->acl_clear_prefetch(); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + // Remove users who are now moderators or admins from everyones foes list + if ($permission_type == 'm_' || $permission_type == 'a_') + { + update_foes($group_id, $user_id); + } + + $this->log_action($mode, 'add', $permission_type, $ug_type, $ug_ids, $forum_ids); + + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + + /** + * Compare auth settings with auth settings from role + * returns false if they differ, true if they are equal + */ + function check_assigned_role($role_id, &$auth_settings) + { + global $db; + + $sql = 'SELECT o.auth_option, r.auth_setting + FROM ' . ACL_OPTIONS_TABLE . ' o, ' . ACL_ROLES_DATA_TABLE . ' r + WHERE o.auth_option_id = r.auth_option_id + AND r.role_id = ' . $role_id; + $result = $db->sql_query($sql); + + $test_auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + $test_auth_settings[$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // We need to add any ACL_NO setting from auth_settings to compare correctly + foreach ($auth_settings as $option => $setting) + { + if ($setting == ACL_NO) + { + $test_auth_settings[$option] = $setting; + } + } + + if (sizeof(array_diff_assoc($auth_settings, $test_auth_settings))) + { + return false; + } + + return true; + } + + /** + * Remove permissions + */ + function remove_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id, &$forum_id) + { + global $user, $db, $auth; + + // User or group to be set? + $ug_type = (sizeof($user_id)) ? 'user' : 'group'; + + // Check the permission setting again + if (!$auth->acl_get('a_' . str_replace('_', '', $permission_type) . 'auth') || !$auth->acl_get('a_auth' . $ug_type . 's')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $auth_admin->acl_delete($ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : false), $permission_type); + + // Do we need to recache the moderator lists? + if ($permission_type == 'm_') + { + cache_moderators(); + } + + $this->log_action($mode, 'del', $permission_type, $ug_type, (($ug_type == 'user') ? $user_id : $group_id), (sizeof($forum_id) ? $forum_id : array(0 => 0))); + + trigger_error($user->lang['AUTH_UPDATED'] . adm_back_link($this->u_action)); + } + + /** + * Log permission changes + */ + function log_action($mode, $action, $permission_type, $ug_type, $ug_id, $forum_id) + { + global $db, $user; + + if (!is_array($ug_id)) + { + $ug_id = array($ug_id); + } + + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + // Logging ... first grab user or groupnames ... + $sql = ($ug_type == 'group') ? 'SELECT group_name as name, group_type FROM ' . GROUPS_TABLE . ' WHERE ' : 'SELECT username as name FROM ' . USERS_TABLE . ' WHERE '; + $sql .= $db->sql_in_set(($ug_type == 'group') ? 'group_id' : 'user_id', array_map('intval', $ug_id)); + $result = $db->sql_query($sql); + + $l_ug_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $l_ug_list .= (($l_ug_list != '') ? ', ' : '') . ((isset($row['group_type']) && $row['group_type'] == GROUP_SPECIAL) ? '<span class="sep">' . $user->lang['G_' . $row['name']] . '</span>' : $row['name']); + } + $db->sql_freeresult($result); + + $mode = str_replace('setting_', '', $mode); + + if ($forum_id[0] == 0) + { + add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_ug_list); + } + else + { + // Grab the forum details if non-zero forum_id + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id); + $result = $db->sql_query($sql); + + $l_forum_list = ''; + while ($row = $db->sql_fetchrow($result)) + { + $l_forum_list .= (($l_forum_list != '') ? ', ' : '') . $row['forum_name']; + } + $db->sql_freeresult($result); + + add_log('admin', 'LOG_ACL_' . strtoupper($action) . '_' . strtoupper($mode) . '_' . strtoupper($permission_type), $l_forum_list, $l_ug_list); + } + } + + /** + * Display a complete trace tree for the selected permission to determine where settings are set/unset + */ + function permission_trace($user_id, $forum_id, $permission) + { + global $db, $template, $user, $auth; + + if ($user_id != $user->data['user_id']) + { + $sql = 'SELECT user_id, username, user_permissions, user_type + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $userdata = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + else + { + $userdata = $user->data; + } + + if (!$userdata) + { + trigger_error('NO_USERS', E_USER_ERROR); + } + + $forum_name = false; + + if ($forum_id) + { + $sql = 'SELECT forum_name + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $forum_id"; + $result = $db->sql_query($sql, 3600); + $forum_name = $db->sql_fetchfield('forum_name'); + $db->sql_freeresult($result); + } + + $back = request_var('back', 0); + + $template->assign_vars(array( + 'PERMISSION' => $user->lang['acl_' . $permission]['lang'], + 'PERMISSION_USERNAME' => $userdata['username'], + 'FORUM_NAME' => $forum_name, + + 'S_GLOBAL_TRACE' => ($forum_id) ? false : true, + + 'U_BACK' => ($back) ? build_url(array('f', 'back')) . "&f=$back" : '') + ); + + $template->assign_block_vars('trace', array( + 'WHO' => $user->lang['DEFAULT'], + 'INFORMATION' => $user->lang['TRACE_DEFAULT'], + + 'S_SETTING_NO' => true, + 'S_TOTAL_NO' => true) + ); + + $sql = 'SELECT DISTINCT g.group_name, g.group_id, g.group_type + FROM ' . GROUPS_TABLE . ' g + LEFT JOIN ' . USER_GROUP_TABLE . ' ug ON (ug.group_id = g.group_id) + WHERE ug.user_id = ' . $user_id . ' + AND ug.user_pending = 0 + ORDER BY g.group_type DESC, g.group_id DESC'; + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups[$row['group_id']] = array( + 'auth_setting' => ACL_NO, + 'group_name' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'] + ); + } + $db->sql_freeresult($result); + + $total = ACL_NO; + $add_key = (($forum_id) ? '_LOCAL' : ''); + + if (sizeof($groups)) + { + // Get group auth settings + $hold_ary = $auth->acl_group_raw_data(array_keys($groups), $permission, $forum_id); + + foreach ($hold_ary as $group_id => $forum_ary) + { + $groups[$group_id]['auth_setting'] = $hold_ary[$group_id][$forum_id][$permission]; + } + unset($hold_ary); + + foreach ($groups as $id => $row) + { + switch ($row['auth_setting']) + { + case ACL_NO: + $information = $user->lang['TRACE_GROUP_NO' . $add_key]; + break; + + case ACL_YES: + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_YES_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_YES_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_GROUP_YES_TOTAL_NO' . $add_key]); + $total = ($total == ACL_NO) ? ACL_YES : $total; + break; + + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_GROUP_NEVER_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_GROUP_NEVER_TOTAL_NO' . $add_key]); + $total = ACL_NEVER; + break; + } + + $template->assign_block_vars('trace', array( + 'WHO' => $row['group_name'], + 'INFORMATION' => $information, + + 'S_SETTING_NO' => ($row['auth_setting'] == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($row['auth_setting'] == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($row['auth_setting'] == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => ($total == ACL_NO) ? true : false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + } + } + + // Get user specific permission... globally or for this forum + $hold_ary = $auth->acl_user_raw_data($user_id, $permission, $forum_id); + $auth_setting = (!sizeof($hold_ary)) ? ACL_NO : $hold_ary[$user_id][$forum_id][$permission]; + + switch ($auth_setting) + { + case ACL_NO: + $information = ($total == ACL_NO) ? $user->lang['TRACE_USER_NO_TOTAL_NO' . $add_key] : $user->lang['TRACE_USER_KEPT' . $add_key]; + $total = ($total == ACL_NO) ? ACL_NEVER : $total; + break; + + case ACL_YES: + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_YES_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_YES_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_USER_YES_TOTAL_NO' . $add_key]); + $total = ($total == ACL_NO) ? ACL_YES : $total; + break; + + case ACL_NEVER: + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_NEVER_TOTAL_YES' . $add_key] : (($total == ACL_NEVER) ? $user->lang['TRACE_USER_NEVER_TOTAL_NEVER' . $add_key] : $user->lang['TRACE_USER_NEVER_TOTAL_NO' . $add_key]); + $total = ACL_NEVER; + break; + } + + $template->assign_block_vars('trace', array( + 'WHO' => $userdata['username'], + 'INFORMATION' => $information, + + 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($auth_setting == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + + if ($forum_id != 0 && isset($auth->acl_options['global'][$permission])) + { + if ($user_id != $user->data['user_id']) + { + $auth2 = new auth(); + $auth2->acl($userdata); + $auth_setting = $auth2->acl_get($permission); + } + else + { + $auth_setting = $auth->acl_get($permission); + } + + if ($auth_setting) + { + $information = ($total == ACL_YES) ? $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_YES'] : $user->lang['TRACE_USER_GLOBAL_YES_TOTAL_NEVER']; + $total = ACL_YES; + } + else + { + $information = $user->lang['TRACE_USER_GLOBAL_NEVER_TOTAL_KEPT']; + } + + // If there is no auth information we do not need to worry the user by showing non-relevant data. + if ($auth_setting) + { + $template->assign_block_vars('trace', array( + 'WHO' => sprintf($user->lang['TRACE_GLOBAL_SETTING'], $userdata['username']), + 'INFORMATION' => sprintf($information, '<a href="' . $this->u_action . "&u=$user_id&f=0&auth=$permission&back=$forum_id\">", '</a>'), + + 'S_SETTING_NO' => false, + 'S_SETTING_YES' => $auth_setting, + 'S_SETTING_NEVER' => !$auth_setting, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => ($total == ACL_YES) ? true : false, + 'S_TOTAL_NEVER' => ($total == ACL_NEVER) ? true : false) + ); + } + } + + // Take founder status into account, overwriting the default values + if ($userdata['user_type'] == USER_FOUNDER && strpos($permission, 'a_') === 0) + { + $template->assign_block_vars('trace', array( + 'WHO' => $userdata['username'], + 'INFORMATION' => $user->lang['TRACE_USER_FOUNDER'], + + 'S_SETTING_NO' => ($auth_setting == ACL_NO) ? true : false, + 'S_SETTING_YES' => ($auth_setting == ACL_YES) ? true : false, + 'S_SETTING_NEVER' => ($auth_setting == ACL_NEVER) ? true : false, + 'S_TOTAL_NO' => false, + 'S_TOTAL_YES' => true, + 'S_TOTAL_NEVER' => false) + ); + + $total = ACL_YES; + } + + // Total value... + $template->assign_vars(array( + 'S_RESULT_NO' => ($total == ACL_NO) ? true : false, + 'S_RESULT_YES' => ($total == ACL_YES) ? true : false, + 'S_RESULT_NEVER' => ($total == ACL_NEVER) ? true : false, + )); + } + + /** + * Get already assigned users/groups + */ + function retrieve_defined_user_groups($permission_scope, $forum_id, $permission_type) + { + global $db, $user; + + $sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0'); + + // Permission options are only able to be a permission set... therefore we will pre-fetch the possible options and also the possible roles + $option_ids = $role_ids = array(); + + $sql = 'SELECT auth_option_id + FROM ' . ACL_OPTIONS_TABLE . ' + WHERE auth_option ' . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $option_ids[] = (int) $row['auth_option_id']; + } + $db->sql_freeresult($result); + + if (sizeof($option_ids)) + { + $sql = 'SELECT DISTINCT role_id + FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE ' . $db->sql_in_set('auth_option_id', $option_ids); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $role_ids[] = (int) $row['role_id']; + } + $db->sql_freeresult($result); + } + + if (sizeof($option_ids) && sizeof($role_ids)) + { + $sql_where = 'AND (' . $db->sql_in_set('a.auth_option_id', $option_ids) . ' OR ' . $db->sql_in_set('a.auth_role_id', $role_ids) . ')'; + } + else + { + $sql_where = 'AND ' . $db->sql_in_set('a.auth_option_id', $option_ids); + } + + // Not ideal, due to the filesort, non-use of indexes, etc. + $sql = 'SELECT DISTINCT u.user_id, u.username, u.username_clean, u.user_regdate + FROM ' . USERS_TABLE . ' u, ' . ACL_USERS_TABLE . " a + WHERE u.user_id = a.user_id + $sql_forum_id + $sql_where + ORDER BY u.username_clean, u.user_regdate ASC"; + $result = $db->sql_query($sql); + + $s_defined_user_options = ''; + $defined_user_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_defined_user_options .= '<option value="' . $row['user_id'] . '">' . $row['username'] . '</option>'; + $defined_user_ids[] = $row['user_id']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT DISTINCT g.group_type, g.group_name, g.group_id + FROM ' . GROUPS_TABLE . ' g, ' . ACL_GROUPS_TABLE . " a + WHERE g.group_id = a.group_id + $sql_forum_id + $sql_where + ORDER BY g.group_type DESC, g.group_name ASC"; + $result = $db->sql_query($sql); + + $s_defined_group_options = ''; + $defined_group_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $s_defined_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + $defined_group_ids[] = $row['group_id']; + } + $db->sql_freeresult($result); + + return array( + 'group_ids' => $defined_group_ids, + 'group_ids_options' => $s_defined_group_options, + 'user_ids' => $defined_user_ids, + 'user_ids_options' => $s_defined_user_options + ); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_php_info.php b/phpBB/modules/acp/acp_php_info.php new file mode 100644 index 0000000000..3df63edc17 --- /dev/null +++ b/phpBB/modules/acp/acp_php_info.php @@ -0,0 +1,83 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_php_info +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + if ($mode != 'info') + { + trigger_error('NO_MODE', E_USER_ERROR); + } + + $this->tpl_name = 'acp_php_info'; + $this->page_title = 'ACP_PHP_INFO'; + + ob_start(); + @phpinfo(INFO_GENERAL | INFO_CONFIGURATION | INFO_MODULES | INFO_VARIABLES); + $phpinfo = ob_get_clean(); + + $phpinfo = trim($phpinfo); + + // Here we play around a little with the PHP Info HTML to try and stylise + // it along phpBB's lines ... hopefully without breaking anything. The idea + // for this was nabbed from the PHP annotated manual + preg_match_all('#<body[^>]*>(.*)</body>#si', $phpinfo, $output); + + if (empty($phpinfo) || empty($output)) + { + trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING); + } + + $output = $output[1][0]; + + // expose_php can make the image not exist + if (preg_match('#<a[^>]*><img[^>]*></a>#', $output)) + { + $output = preg_replace('#<tr class="v"><td>(.*?<a[^>]*><img[^>]*></a>)(.*?)</td></tr>#s', '<tr class="row1"><td><table class="type2"><tr><td>\2</td><td>\1</td></tr></table></td></tr>', $output); + } + else + { + $output = preg_replace('#<tr class="v"><td>(.*?)</td></tr>#s', '<tr class="row1"><td><table class="type2"><tr><td>\1</td></tr></table></td></tr>', $output); + } + $output = preg_replace('#<table[^>]+>#i', '<table>', $output); + $output = preg_replace('#<img border="0"#i', '<img', $output); + $output = str_replace(array('class="e"', 'class="v"', 'class="h"', '<hr />', '<font', '</font>'), array('class="row1"', 'class="row2"', '', '', '<span', '</span>'), $output); + + if (empty($output)) + { + trigger_error('NO_PHPINFO_AVAILABLE', E_USER_WARNING); + } + + $orig_output = $output; + + preg_match_all('#<div class="center">(.*)</div>#siU', $output, $output); + $output = (!empty($output[1][0])) ? $output[1][0] : $orig_output; + + $template->assign_var('PHPINFO', $output); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_profile.php b/phpBB/modules/acp/acp_profile.php new file mode 100644 index 0000000000..4143b70434 --- /dev/null +++ b/phpBB/modules/acp/acp_profile.php @@ -0,0 +1,1661 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_profile +{ + var $u_action; + + var $edit_lang_id; + var $lang_defs; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + include(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); + + $user->add_lang(array('ucp', 'acp/profile')); + $this->tpl_name = 'acp_profile'; + $this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS'; + + $action = (request::is_set_post('create')) ? 'create' : request_var('action', ''); + + $error = array(); + $s_hidden_fields = ''; + + // Define some default values for each field type + $default_values = array( + FIELD_STRING => array('field_length' => 10, 'field_minlen' => 0, 'field_maxlen' => 20, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), + FIELD_TEXT => array('field_length' => '5|80', 'field_minlen' => 0, 'field_maxlen' => 1000, 'field_validation' => '.*', 'field_novalue' => '', 'field_default_value' => ''), + FIELD_INT => array('field_length' => 5, 'field_minlen' => 0, 'field_maxlen' => 100, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + FIELD_DATE => array('field_length' => 10, 'field_minlen' => 10, 'field_maxlen' => 10, 'field_validation' => '', 'field_novalue' => ' 0- 0- 0', 'field_default_value' => ' 0- 0- 0'), + FIELD_BOOL => array('field_length' => 1, 'field_minlen' => 0, 'field_maxlen' => 0, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + FIELD_DROPDOWN => array('field_length' => 0, 'field_minlen' => 0, 'field_maxlen' => 5, 'field_validation' => '', 'field_novalue' => 0, 'field_default_value' => 0), + ); + + $cp = new custom_profile_admin(); + + // Build Language array + // Based on this, we decide which elements need to be edited later and which language items are missing + $this->lang_defs = array(); + + $sql = 'SELECT lang_id, lang_iso + FROM ' . LANG_TABLE . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Make some arrays with all available languages + $this->lang_defs['id'][$row['lang_id']] = $row['lang_iso']; + $this->lang_defs['iso'][$row['lang_iso']] = $row['lang_id']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT field_id, lang_id + FROM ' . PROFILE_LANG_TABLE . ' + ORDER BY lang_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Which languages are available for each item + $this->lang_defs['entry'][$row['field_id']][] = $row['lang_id']; + } + $db->sql_freeresult($result); + + // Have some fields been defined? + if (isset($this->lang_defs['entry'])) + { + foreach ($this->lang_defs['entry'] as $field_id => $field_ary) + { + // Fill an array with the languages that are missing for each field + $this->lang_defs['diff'][$field_id] = array_diff(array_values($this->lang_defs['iso']), $field_ary); + } + } + + switch ($action) + { + case 'delete': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + $db->sql_transaction('begin'); + + $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_TABLE . " WHERE field_id = $field_id"); + $db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id"); + $db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id"); + + if ($db->dbms_type == 'sqlite') + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create a temp table and populate it, destroy the existing one + $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = preg_split('/,(?=[\\sa-z])/im', $new_table_cols); + $column_list = array(); + + foreach ($old_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + + if ($entities[0] == 'PRIMARY') + { + continue; + } + + if ($entities[0] !== 'pf_' . $field_ident) + { + $column_list[] = $entities[0]; + } + } + + $columns = implode(',', $column_list); + + $new_table_cols = preg_replace('/' . 'pf_' . $field_ident . '[^,]+,/', '', $new_table_cols); + + // create a new table and fill it up. destroy the temp one + $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); + } + else + { + $db->sql_query('ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " DROP COLUMN pf_$field_ident"); + } + + $order = 0; + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_TABLE . ' + ORDER BY field_order'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $order++; + if ($row['field_order'] != $order) + { + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_order = $order + WHERE field_id = {$row['field_id']}"; + $db->sql_query($sql); + } + } + $db->sql_freeresult($result); + + $db->sql_transaction('commit'); + + add_log('admin', 'LOG_PROFILE_FIELD_REMOVED', $field_ident); + trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, 'DELETE_PROFILE_FIELD', build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'field_id' => $field_id, + ))); + } + + break; + + case 'activate': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'"; + $result = $db->sql_query($sql); + $default_lang_id = (int) $db->sql_fetchfield('lang_id'); + $db->sql_freeresult($result); + + if (!in_array($default_lang_id, $this->lang_defs['entry'][$field_id])) + { + trigger_error($user->lang['DEFAULT_LANGUAGE_NOT_FILLED'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_active = 1 + WHERE field_id = $field_id"; + $db->sql_query($sql); + + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident); + trigger_error($user->lang['PROFILE_FIELD_ACTIVATED'] . adm_back_link($this->u_action)); + + break; + + case 'deactivate': + $field_id = request_var('field_id', 0); + + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_active = 0 + WHERE field_id = $field_id"; + $db->sql_query($sql); + + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_id = $field_id"; + $result = $db->sql_query($sql); + $field_ident = (string) $db->sql_fetchfield('field_ident'); + $db->sql_freeresult($result); + + add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident); + trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action)); + + break; + + case 'move_up': + case 'move_down': + $field_order = request_var('order', 0); + $order_total = $field_order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . " + SET field_order = $order_total - field_order + WHERE field_order IN ($field_order, " . (($action == 'move_up') ? $field_order - 1 : $field_order + 1) . ')'; + $db->sql_query($sql); + + break; + + case 'create': + case 'edit': + + $field_id = request_var('field_id', 0); + $step = request_var('step', 1); + + $submit = (request::is_set('next') || request::is_set('prev')) ? true : false; + $save = request::is_set('save'); + + // The language id of default language + $this->edit_lang_id = $this->lang_defs['iso'][$config['default_lang']]; + + // We are editing... we need to grab basic things + if ($action == 'edit') + { + if (!$field_id) + { + trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT l.*, f.* + FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f + WHERE l.lang_id = ' . $this->edit_lang_id . " + AND f.field_id = $field_id + AND l.field_id = f.field_id"; + $result = $db->sql_query($sql); + $field_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$field_row) + { + // Some admin changed the default language? + $sql = 'SELECT l.*, f.* + FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f + WHERE l.lang_id <> ' . $this->edit_lang_id . " + AND f.field_id = $field_id + AND l.field_id = f.field_id"; + $result = $db->sql_query($sql); + $field_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$field_row) + { + trigger_error($user->lang['FIELD_NOT_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->edit_lang_id = $field_row['lang_id']; + } + $field_type = $field_row['field_type']; + + // Get language entries + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id = ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY option_id ASC"; + $result = $db->sql_query($sql); + + $lang_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $lang_options[$row['option_id']] = $row['lang_value']; + } + $db->sql_freeresult($result); + + $s_hidden_fields = '<input type="hidden" name="field_id" value="' . $field_id . '" />'; + } + else + { + // We are adding a new field, define basic params + $lang_options = $field_row = array(); + + $field_type = request_var('field_type', 0); + + if (!$field_type) + { + trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $field_row = array_merge($default_values[$field_type], array( + 'field_ident' => utf8_clean_string(request_var('field_ident', '', true)), + 'field_required' => 0, + 'field_hide' => 0, + 'field_no_view' => 0, + 'field_show_on_reg' => 0, + 'lang_name' => utf8_normalize_nfc(request_var('field_ident', '', true)), + 'lang_explain' => '', + 'lang_default_value'=> '') + ); + + $s_hidden_fields = '<input type="hidden" name="field_type" value="' . $field_type . '" />'; + } + + // $exclude contains the data we gather in each step + $exclude = array( + 1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option', 'field_no_view'), + 2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'), + 3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options') + ); + + // Text-based fields require the lang_default_value to be excluded + if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) + { + $exclude[1][] = 'lang_default_value'; + } + + // option-specific fields require lang_options to be excluded + if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) + { + $exclude[1][] = 'lang_options'; + } + + $cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string(request_var('field_ident', $field_row['field_ident'], true)) : request_var('field_ident', $field_row['field_ident']); + $cp->vars['lang_name'] = utf8_normalize_nfc(request_var('lang_name', $field_row['lang_name'], true)); + $cp->vars['lang_explain'] = utf8_normalize_nfc(request_var('lang_explain', $field_row['lang_explain'], true)); + $cp->vars['lang_default_value'] = utf8_normalize_nfc(request_var('lang_default_value', $field_row['lang_default_value'], true)); + + // Field option... + if (request::is_set('field_option')) + { + $field_option = request_var('field_option', ''); + + $cp->vars['field_required'] = ($field_option == 'field_required') ? 1 : 0; + $cp->vars['field_show_on_reg'] = ($field_option == 'field_show_on_reg') ? 1 : 0; + $cp->vars['field_hide'] = ($field_option == 'field_hide') ? 1 : 0; + } + else + { + $cp->vars['field_required'] = $field_row['field_required']; + $cp->vars['field_show_on_reg'] = $field_row['field_show_on_reg']; + $cp->vars['field_hide'] = $field_row['field_hide']; + + $field_option = ($field_row['field_required']) ? 'field_required' : (($field_row['field_show_on_reg']) ? 'field_show_on_reg' : (($field_row['field_hide']) ? 'field_hide' : '')); + } + + $cp->vars['field_no_view'] = request_var('field_no_view', $field_row['field_no_view']); + + // A boolean field expects an array as the lang options + if ($field_type == FIELD_BOOL) + { + $options = utf8_normalize_nfc(request_var('lang_options', array(''), true)); + } + else + { + $options = utf8_normalize_nfc(request_var('lang_options', '', true)); + } + + // If the user has submitted a form with options (i.e. dropdown field) + if ($options) + { + $exploded_options = (is_array($options)) ? $options : explode("\n", $options); + + if (sizeof($exploded_options) == sizeof($lang_options) || $action == 'create') + { + // The number of options in the field is equal to the number of options already in the database + // Or we are creating a new dropdown list. + $cp->vars['lang_options'] = $exploded_options; + } + else if ($action == 'edit') + { + // Changing the number of options? (We remove and re-create the option fields) + $cp->vars['lang_options'] = $exploded_options; + } + } + else + { + $cp->vars['lang_options'] = $lang_options; + } + + // step 2 + foreach ($exclude[2] as $key) + { + $var = utf8_normalize_nfc(request_var($key, $field_row[$key], true)); + + // Manipulate the intended variables a little bit if needed + if ($field_type == FIELD_DROPDOWN && $key == 'field_maxlen') + { + // Get the number of options if this key is 'field_maxlen' + $var = sizeof(explode("\n", utf8_normalize_nfc(request_var('lang_options', '', true)))); + } + else if ($field_type == FIELD_TEXT && $key == 'field_length') + { + if (request::is_set('rows')) + { + $cp->vars['rows'] = request_var('rows', 0); + $cp->vars['columns'] = request_var('columns', 0); + $var = $cp->vars['rows'] . '|' . $cp->vars['columns']; + } + else + { + $row_col = explode('|', $var); + $cp->vars['rows'] = $row_col[0]; + $cp->vars['columns'] = $row_col[1]; + } + } + else if ($field_type == FIELD_DATE && $key == 'field_default_value') + { + $always_now = request_var('always_now', -1); + + if ($always_now == 1 || ($always_now === -1 && $var == 'now')) + { + $now = getdate(); + + $cp->vars['field_default_value_day'] = $now['mday']; + $cp->vars['field_default_value_month'] = $now['mon']; + $cp->vars['field_default_value_year'] = $now['year']; + + $var = 'now'; + /** + * @todo Do NOT overwrite a request variable. + */ + request::overwrite('field_default_value', $var, request::REQUEST); + request::overwrite('field_default_value', $var, request::POST); + } + else + { + if (request::is_set('field_default_value_day')) + { + $cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); + $cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); + $cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); + $var = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + /** + * @todo Do NOT overwrite a request variable. + */ + request::overwrite('field_default_value', $var, request::REQUEST); + request::overwrite('field_default_value', $var, request::POST); + } + else + { + list($cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']) = explode('-', $var); + } + } + } + /* else if ($field_type == FIELD_BOOL && $key == 'field_default_value') + { + // Get the number of options if this key is 'field_maxlen' + $var = request_var('field_default_value', 0); + }*/ + + $cp->vars[$key] = $var; + } + + // step 3 - all arrays + if ($action == 'edit') + { + // Get language entries + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_LANG_TABLE . ' + WHERE lang_id <> ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY option_id ASC"; + $result = $db->sql_query($sql); + + $l_lang_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + $l_lang_options[$row['lang_id']][$row['option_id']] = $row['lang_value']; + } + $db->sql_freeresult($result); + + + $sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value + FROM ' . PROFILE_LANG_TABLE . ' + WHERE lang_id <> ' . $this->edit_lang_id . " + AND field_id = $field_id + ORDER BY lang_id ASC"; + $result = $db->sql_query($sql); + + $l_lang_name = $l_lang_explain = $l_lang_default_value = array(); + while ($row = $db->sql_fetchrow($result)) + { + $l_lang_name[$row['lang_id']] = $row['lang_name']; + $l_lang_explain[$row['lang_id']] = $row['lang_explain']; + $l_lang_default_value[$row['lang_id']] = $row['lang_default_value']; + } + $db->sql_freeresult($result); + } + + foreach ($exclude[3] as $key) + { + $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => ''), true)); + + if (!$cp->vars[$key] && $action == 'edit') + { + $cp->vars[$key] = $$key; + } + else if ($key == 'l_lang_options' && $field_type == FIELD_BOOL) + { + $cp->vars[$key] = utf8_normalize_nfc(request_var($key, array(0 => array('')), true)); + } + else if ($key == 'l_lang_options' && is_array($cp->vars[$key])) + { + foreach ($cp->vars[$key] as $lang_id => $options) + { + $cp->vars[$key][$lang_id] = explode("\n", $options); + } + + } + } + + // Check for general issues in every step + if ($submit) // && $step == 1 + { + // Check values for step 1 + if ($cp->vars['field_ident'] == '') + { + $error[] = $user->lang['EMPTY_FIELD_IDENT']; + } + + if (!preg_match('/^[a-z_]+$/', $cp->vars['field_ident'])) + { + $error[] = $user->lang['INVALID_CHARS_FIELD_IDENT']; + } + + if (strlen($cp->vars['field_ident']) > 17) + { + $error[] = $user->lang['INVALID_FIELD_IDENT_LEN']; + } + + if ($cp->vars['lang_name'] == '') + { + $error[] = $user->lang['EMPTY_USER_FIELD_NAME']; + } + + if ($field_type == FIELD_DROPDOWN && !sizeof($cp->vars['lang_options'])) + { + $error[] = $user->lang['NO_FIELD_ENTRIES']; + } + + if ($field_type == FIELD_BOOL && (empty($cp->vars['lang_options'][0]) || empty($cp->vars['lang_options'][1]))) + { + $error[] = $user->lang['NO_FIELD_ENTRIES']; + } + + // Check for already existing field ident + if ($action != 'edit') + { + $sql = 'SELECT field_ident + FROM ' . PROFILE_FIELDS_TABLE . " + WHERE field_ident = '" . $db->sql_escape($cp->vars['field_ident']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $error[] = $user->lang['FIELD_IDENT_ALREADY_EXIST']; + } + } + } + + $step = (request::is_set('next')) ? $step + 1 : ((request::is_set('prev')) ? $step - 1 : $step); + + if (sizeof($error)) + { + $step--; + $submit = false; + } + + // Build up the specific hidden fields + foreach ($exclude as $num => $key_ary) + { + if ($num == $step) + { + continue; + } + + $_new_key_ary = array(); + + foreach ($key_ary as $key) + { + if ($field_type == FIELD_TEXT && $key == 'field_length' && request::is_set('rows')) + { + $cp->vars['rows'] = request_var('rows', 0); + $cp->vars['columns'] = request_var('columns', 0); + $_new_key_ary[$key] = $cp->vars['rows'] . '|' . $cp->vars['columns']; + } + else if ($field_type == FIELD_DATE && $key == 'field_default_value') + { + $always_now = request_var('always_now', 0); + + if ($always_now) + { + $_new_key_ary[$key] = 'now'; + } + else if (request::is_set('field_default_value_day')) + { + $cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); + $cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); + $cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); + $_new_key_ary[$key] = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + } + } + else if ($field_type == FIELD_BOOL && $key == 'l_lang_options' && request::is_set('l_lang_options')) + { + $_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(array('')), true)); + } + else + { + if (!request::is_set($key)) + { + $var = false; + } + else if ($key == 'field_ident' && isset($cp->vars[$key])) + { + $_new_key_ary[$key]= $cp->vars[$key]; + } + else + { + $_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(''), true)); + if (!sizeof($_new_key_ary[$key])) + { + $_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, '', true)); + } + } + } + } + + $s_hidden_fields .= build_hidden_fields($_new_key_ary); + } + + if (!sizeof($error)) + { + if ($step == 3 && (sizeof($this->lang_defs['iso']) == 1 || $save)) + { + $this->save_profile_field($cp, $field_type, $action); + } + else if ($action == 'edit' && $save) + { + $this->save_profile_field($cp, $field_type, $action); + } + } + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_EDIT_MODE' => ($action == 'edit') ? true : false, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'L_TITLE' => $user->lang['STEP_' . $step . '_TITLE_' . strtoupper($action)], + 'L_EXPLAIN' => $user->lang['STEP_' . $step . '_EXPLAIN_' . strtoupper($action)], + + 'U_ACTION' => $this->u_action . "&action=$action&step=$step", + 'U_BACK' => $this->u_action) + ); + + // Now go through the steps + switch ($step) + { + // Create basic options - only small differences between field types + case 1: + + // Build common create options + $template->assign_vars(array( + 'S_STEP_ONE' => true, + 'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false, + 'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false, + 'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false, + 'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false, + + 'L_LANG_SPECIFIC' => sprintf($user->lang['LANG_SPECIFIC_OPTIONS'], $config['default_lang']), + 'FIELD_TYPE' => $user->lang['FIELD_' . strtoupper(custom_profile::$profile_types[$field_type])], + 'FIELD_IDENT' => $cp->vars['field_ident'], + 'LANG_NAME' => $cp->vars['lang_name'], + 'LANG_EXPLAIN' => $cp->vars['lang_explain']) + ); + + // String and Text needs to set default values here... + if ($field_type == FIELD_STRING || $field_type == FIELD_TEXT) + { + $template->assign_vars(array( + 'S_TEXT' => ($field_type == FIELD_TEXT) ? true : false, + 'S_STRING' => ($field_type == FIELD_STRING) ? true : false, + + 'L_DEFAULT_VALUE_EXPLAIN' => $user->lang[strtoupper(custom_profile::$profile_types[$field_type]) . '_DEFAULT_VALUE_EXPLAIN'], + 'LANG_DEFAULT_VALUE' => $cp->vars['lang_default_value']) + ); + } + + if ($field_type == FIELD_BOOL || $field_type == FIELD_DROPDOWN) + { + // Initialize these array elements if we are creating a new field + if (!sizeof($cp->vars['lang_options'])) + { + if ($field_type == FIELD_BOOL) + { + // No options have been defined for a boolean field. + $cp->vars['lang_options'][0] = ''; + $cp->vars['lang_options'][1] = ''; + } + else + { + // No options have been defined for the dropdown menu + $cp->vars['lang_options'] = array(); + } + } + + $template->assign_vars(array( + 'S_BOOL' => ($field_type == FIELD_BOOL) ? true : false, + 'S_DROPDOWN' => ($field_type == FIELD_DROPDOWN) ? true : false, + + 'L_LANG_OPTIONS_EXPLAIN' => $user->lang[strtoupper(custom_profile::$profile_types[$field_type]) . '_ENTRIES_EXPLAIN'], + 'LANG_OPTIONS' => ($field_type == FIELD_DROPDOWN) ? implode("\n", $cp->vars['lang_options']) : '', + 'FIRST_LANG_OPTION' => ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][0] : '', + 'SECOND_LANG_OPTION' => ($field_type == FIELD_BOOL) ? $cp->vars['lang_options'][1] : '') + ); + } + + break; + + case 2: + + $template->assign_vars(array( + 'S_STEP_TWO' => true, + 'L_NEXT_STEP' => (sizeof($this->lang_defs['iso']) == 1) ? $user->lang['SAVE'] : $user->lang['PROFILE_LANG_OPTIONS']) + ); + + // Build options based on profile type + $function = 'get_' . custom_profile::$profile_types[$field_type] . '_options'; + $options = $cp->$function(); + + foreach ($options as $num => $option_ary) + { + $template->assign_block_vars('option', $option_ary); + } + + break; + + // Define remaining language variables + case 3: + + $template->assign_var('S_STEP_THREE', true); + $options = $this->build_language_options($cp, $field_type, $action); + + foreach ($options as $lang_id => $lang_ary) + { + $template->assign_block_vars('options', array( + 'LANGUAGE' => sprintf($user->lang[(($lang_id == $this->edit_lang_id) ? 'DEFAULT_' : '') . 'ISO_LANGUAGE'], $lang_ary['lang_iso'])) + ); + + foreach ($lang_ary['fields'] as $field_ident => $field_ary) + { + $template->assign_block_vars('options.field', array( + 'L_TITLE' => $field_ary['TITLE'], + 'L_EXPLAIN' => (isset($field_ary['EXPLAIN'])) ? $field_ary['EXPLAIN'] : '', + 'FIELD' => $field_ary['FIELD']) + ); + } + } + + break; + } + + $template->assign_vars(array( + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + return; + + break; + } + + $sql = 'SELECT * + FROM ' . PROFILE_FIELDS_TABLE . ' + ORDER BY field_order'; + $result = $db->sql_query($sql); + + $s_one_need_edit = false; + while ($row = $db->sql_fetchrow($result)) + { + $active_lang = (!$row['field_active']) ? 'ACTIVATE' : 'DEACTIVATE'; + $active_value = (!$row['field_active']) ? 'activate' : 'deactivate'; + $id = $row['field_id']; + + $s_need_edit = (sizeof($this->lang_defs['diff'][$row['field_id']])) ? true : false; + + if ($s_need_edit) + { + $s_one_need_edit = true; + } + + $template->assign_block_vars('fields', array( + 'FIELD_IDENT' => $row['field_ident'], + 'FIELD_TYPE' => $user->lang['FIELD_' . strtoupper(custom_profile::$profile_types[$row['field_type']])], + + 'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang], + 'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&action=$active_value&field_id=$id", + 'U_EDIT' => $this->u_action . "&action=edit&field_id=$id", + 'U_TRANSLATE' => $this->u_action . "&action=edit&field_id=$id&step=3", + 'U_DELETE' => $this->u_action . "&action=delete&field_id=$id", + 'U_MOVE_UP' => $this->u_action . "&action=move_up&order={$row['field_order']}", + 'U_MOVE_DOWN' => $this->u_action . "&action=move_down&order={$row['field_order']}", + + 'S_NEED_EDIT' => $s_need_edit) + ); + } + $db->sql_freeresult($result); + + // At least one option field needs editing? + if ($s_one_need_edit) + { + $template->assign_var('S_NEED_EDIT', true); + } + + $s_select_type = ''; + foreach (custom_profile::$profile_types as $key => $value) + { + $s_select_type .= '<option value="' . $key . '">' . $user->lang['FIELD_' . strtoupper($value)] . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_TYPE_OPTIONS' => $s_select_type) + ); + } + + /** + * Build all Language specific options + */ + function build_language_options(&$cp, $field_type, $action = 'create') + { + global $user, $config, $db; + + $default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; + + $sql = 'SELECT lang_id, lang_iso + FROM ' . LANG_TABLE . ' + WHERE lang_id <> ' . (int) $default_lang_id . ' + ORDER BY lang_english_name'; + $result = $db->sql_query($sql); + + $languages = array(); + while ($row = $db->sql_fetchrow($result)) + { + $languages[$row['lang_id']] = $row['lang_iso']; + } + $db->sql_freeresult($result); + + $options = array(); + $options['lang_name'] = 'string'; + if ($cp->vars['lang_explain']) + { + $options['lang_explain'] = 'text'; + } + + switch ($field_type) + { + case FIELD_BOOL: + $options['lang_options'] = 'two_options'; + break; + + case FIELD_DROPDOWN: + $options['lang_options'] = 'optionfield'; + break; + + case FIELD_TEXT: + case FIELD_STRING: + if ($cp->vars['lang_default_value']) + { + $options['lang_default_value'] = ($field_type == FIELD_STRING) ? 'string' : 'text'; + } + break; + } + + $lang_options = array(); + + foreach ($options as $field => $field_type) + { + $lang_options[1]['lang_iso'] = $this->lang_defs['id'][$default_lang_id]; + $lang_options[1]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => '<dd>' . ((is_array($cp->vars[$field])) ? implode('<br />', $cp->vars[$field]) : bbcode_nl2br($cp->vars[$field])) . '</dd>' + ); + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[1]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + + foreach ($languages as $lang_id => $lang_iso) + { + $lang_options[$lang_id]['lang_iso'] = $lang_iso; + foreach ($options as $field => $field_type) + { + $value = ($action == 'create') ? utf8_normalize_nfc(request_var('l_' . $field, array(0 => ''), true)) : $cp->vars['l_' . $field]; + if ($field == 'lang_options') + { + $var = (!isset($cp->vars['l_lang_options'][$lang_id]) || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['l_lang_options'][$lang_id]; + + switch ($field_type) + { + case 'two_options': + + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => ' + <dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][0])) ? $value[$lang_id][0] : $var[0]) . '" /> ' . $user->lang['FIRST_OPTION'] . '</dd> + <dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][1])) ? $value[$lang_id][1] : $var[1]) . '" /> ' . $user->lang['SECOND_OPTION'] . '</dd>' + ); + break; + + case 'optionfield': + $value = ((isset($value[$lang_id])) ? ((is_array($value[$lang_id])) ? implode("\n", $value[$lang_id]) : $value[$lang_id]) : implode("\n", $var)); + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="7" cols="80">' . $value . '</textarea></dd>' + ); + break; + } + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + else + { + $var = ($action == 'create' || !is_array($cp->vars[$field])) ? $cp->vars[$field] : $cp->vars[$field][$lang_id]; + + $lang_options[$lang_id]['fields'][$field] = array( + 'TITLE' => $user->lang['CP_' . strtoupper($field)], + 'FIELD' => ($field_type == 'string') ? '<dd><input class="medium" type="text" name="l_' . $field . '[' . $lang_id . ']" value="' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '" /></dd>' : '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="3" cols="80">' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '</textarea></dd>' + ); + + if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN'])) + { + $lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN']; + } + } + } + } + + return $lang_options; + } + + /** + * Save Profile Field + */ + function save_profile_field(&$cp, $field_type, $action = 'create') + { + global $db, $config, $user; + + $field_id = request_var('field_id', 0); + + // Collect all information, if something is going wrong, abort the operation + $profile_sql = $profile_lang = $empty_lang = $profile_lang_fields = array(); + + $default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']]; + + if ($action == 'create') + { + $sql = 'SELECT MAX(field_order) as max_field_order + FROM ' . PROFILE_FIELDS_TABLE; + $result = $db->sql_query($sql); + $new_field_order = (int) $db->sql_fetchfield('max_field_order'); + $db->sql_freeresult($result); + + $field_ident = $cp->vars['field_ident']; + } + + // Save the field + $profile_fields = array( + 'field_length' => $cp->vars['field_length'], + 'field_minlen' => $cp->vars['field_minlen'], + 'field_maxlen' => $cp->vars['field_maxlen'], + 'field_novalue' => $cp->vars['field_novalue'], + 'field_default_value' => $cp->vars['field_default_value'], + 'field_validation' => $cp->vars['field_validation'], + 'field_required' => $cp->vars['field_required'], + 'field_show_on_reg' => $cp->vars['field_show_on_reg'], + 'field_hide' => $cp->vars['field_hide'], + 'field_no_view' => $cp->vars['field_no_view'] + ); + + if ($action == 'create') + { + $profile_fields += array( + 'field_type' => $field_type, + 'field_ident' => $field_ident, + 'field_name' => $field_ident, + 'field_order' => $new_field_order + 1, + 'field_active' => 1 + ); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $db->sql_build_array('INSERT', $profile_fields); + $db->sql_query($sql); + + $field_id = $db->sql_nextid(); + } + else + { + $sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $profile_fields) . " + WHERE field_id = $field_id"; + $db->sql_query($sql); + } + + if ($action == 'create') + { + $field_ident = 'pf_' . $field_ident; + $profile_sql[] = $this->add_field_ident($field_ident, $field_type); + } + + $sql_ary = array( + 'lang_name' => $cp->vars['lang_name'], + 'lang_explain' => $cp->vars['lang_explain'], + 'lang_default_value' => $cp->vars['lang_default_value'] + ); + + if ($action == 'create') + { + $sql_ary['field_id'] = $field_id; + $sql_ary['lang_id'] = $default_lang_id; + + $profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + else + { + $this->update_insert(PROFILE_LANG_TABLE, $sql_ary, array('field_id' => $field_id, 'lang_id' => $default_lang_id)); + } + + if (is_array($cp->vars['l_lang_name']) && sizeof($cp->vars['l_lang_name'])) + { + foreach ($cp->vars['l_lang_name'] as $lang_id => $data) + { + if (($cp->vars['lang_name'] != '' && $cp->vars['l_lang_name'][$lang_id] == '') + || ($cp->vars['lang_explain'] != '' && $cp->vars['l_lang_explain'][$lang_id] == '') + || ($cp->vars['lang_default_value'] != '' && $cp->vars['l_lang_default_value'][$lang_id] == '')) + { + $empty_lang[$lang_id] = true; + break; + } + + if (!isset($empty_lang[$lang_id])) + { + $profile_lang[] = array( + 'field_id' => $field_id, + 'lang_id' => $lang_id, + 'lang_name' => $cp->vars['l_lang_name'][$lang_id], + 'lang_explain' => (isset($cp->vars['l_lang_explain'][$lang_id])) ? $cp->vars['l_lang_explain'][$lang_id] : '', + 'lang_default_value' => (isset($cp->vars['l_lang_default_value'][$lang_id])) ? $cp->vars['l_lang_default_value'][$lang_id] : '' + ); + } + } + + foreach ($empty_lang as $lang_id => $NULL) + { + $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + } + + // These are always arrays because the key is the language id... + $cp->vars['l_lang_name'] = utf8_normalize_nfc(request_var('l_lang_name', array(0 => ''), true)); + $cp->vars['l_lang_explain'] = utf8_normalize_nfc(request_var('l_lang_explain', array(0 => ''), true)); + $cp->vars['l_lang_default_value'] = utf8_normalize_nfc(request_var('l_lang_default_value', array(0 => ''), true)); + + if ($field_type != FIELD_BOOL) + { + $cp->vars['l_lang_options'] = utf8_normalize_nfc(request_var('l_lang_options', array(0 => ''), true)); + } + else + { + /** + * @todo check if this line is correct... + $cp->vars['l_lang_default_value'] = request_var('l_lang_default_value', array(0 => array('')), true); + */ + $cp->vars['l_lang_options'] = utf8_normalize_nfc(request_var('l_lang_options', array(0 => array('')), true)); + } + + if ($cp->vars['lang_options']) + { + if (!is_array($cp->vars['lang_options'])) + { + $cp->vars['lang_options'] = explode("\n", $cp->vars['lang_options']); + } + + if ($action != 'create') + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $default_lang_id; + $db->sql_query($sql); + } + + foreach ($cp->vars['lang_options'] as $option_id => $value) + { + $sql_ary = array( + 'field_type' => (int) $field_type, + 'lang_value' => $value + ); + + if ($action == 'create') + { + $sql_ary['field_id'] = $field_id; + $sql_ary['lang_id'] = $default_lang_id; + $sql_ary['option_id'] = (int) $option_id; + + $profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + } + else + { + $this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql_ary, array( + 'field_id' => $field_id, + 'lang_id' => (int) $default_lang_id, + 'option_id' => (int) $option_id) + ); + } + } + } + + if (is_array($cp->vars['l_lang_options']) && sizeof($cp->vars['l_lang_options'])) + { + $empty_lang = array(); + + foreach ($cp->vars['l_lang_options'] as $lang_id => $lang_ary) + { + if (!is_array($lang_ary)) + { + $lang_ary = explode("\n", $lang_ary); + } + + if (sizeof($lang_ary) != sizeof($cp->vars['lang_options'])) + { + $empty_lang[$lang_id] = true; + } + + if (!isset($empty_lang[$lang_id])) + { + if ($action != 'create') + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + + foreach ($lang_ary as $option_id => $value) + { + $profile_lang_fields[] = array( + 'field_id' => (int) $field_id, + 'lang_id' => (int) $lang_id, + 'option_id' => (int) $option_id, + 'field_type' => (int) $field_type, + 'lang_value' => $value + ); + } + } + } + + foreach ($empty_lang as $lang_id => $NULL) + { + $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " + WHERE field_id = $field_id + AND lang_id = " . (int) $lang_id; + $db->sql_query($sql); + } + } + + foreach ($profile_lang as $sql) + { + if ($action == 'create') + { + $profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql); + } + else + { + $lang_id = $sql['lang_id']; + unset($sql['lang_id'], $sql['field_id']); + + $this->update_insert(PROFILE_LANG_TABLE, $sql, array('lang_id' => (int) $lang_id, 'field_id' => $field_id)); + } + } + + if (sizeof($profile_lang_fields)) + { + foreach ($profile_lang_fields as $sql) + { + if ($action == 'create') + { + $profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql); + } + else + { + $lang_id = $sql['lang_id']; + $option_id = $sql['option_id']; + unset($sql['lang_id'], $sql['field_id'], $sql['option_id']); + + $this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql, array( + 'lang_id' => $lang_id, + 'field_id' => $field_id, + 'option_id' => $option_id) + ); + } + } + } + + + $db->sql_transaction('begin'); + + if ($action == 'create') + { + foreach ($profile_sql as $sql) + { + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + + if ($action == 'edit') + { + add_log('admin', 'LOG_PROFILE_FIELD_EDIT', $cp->vars['field_ident'] . ':' . $cp->vars['lang_name']); + trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + else + { + add_log('admin', 'LOG_PROFILE_FIELD_CREATE', substr($field_ident, 3) . ':' . $cp->vars['lang_name']); + trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action)); + } + } + + /** + * Update, then insert if not successfull + */ + function update_insert($table, $sql_ary, $where_fields) + { + global $db; + + $where_sql = array(); + $check_key = ''; + + foreach ($where_fields as $key => $value) + { + $check_key = (!$check_key) ? $key : $check_key; + $where_sql[] = $key . ' = ' . ((is_string($value)) ? "'" . $db->sql_escape($value) . "'" : (int) $value); + } + + if (!sizeof($where_sql)) + { + return; + } + + $sql = "SELECT $check_key + FROM $table + WHERE " . implode(' AND ', $where_sql); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $sql_ary = array_merge($where_fields, $sql_ary); + + if (sizeof($sql_ary)) + { + $db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql_ary)); + } + } + else + { + if (sizeof($sql_ary)) + { + $sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE ' . implode(' AND ', $where_sql); + $db->sql_query($sql); + } + } + } + + /** + * Return sql statement for adding a new field ident (profile field) to the profile fields data table + */ + function add_field_ident($field_ident, $field_type) + { + global $db; + + switch ($db->dbms_type) + { + case 'mysql': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD `$field_ident` "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'TINYINT(2) '; + break; + + case FIELD_DROPDOWN: + $sql .= 'MEDIUMINT(8) '; + break; + + case FIELD_INT: + $sql .= 'BIGINT(20) '; + break; + } + + break; + + case 'sqlite': + + switch ($field_type) + { + case FIELD_STRING: + $type = ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $type = 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $type = "TEXT(65535)"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $type = 'TINYINT(2) '; + break; + + case FIELD_DROPDOWN: + $type = 'MEDIUMINT(8) '; + break; + + case FIELD_INT: + $type = 'BIGINT(20) '; + break; + } + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + if (version_compare(sqlite_libversion(), '3.0') == -1) + { + $sql = "SELECT sql + FROM sqlite_master + WHERE type = 'table' + AND name = '" . PROFILE_FIELDS_DATA_TABLE . "' + ORDER BY type DESC, name;"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Create a temp table and populate it, destroy the existing one + $db->sql_query(preg_replace('#CREATE\s+TABLE\s+"?' . PROFILE_FIELDS_DATA_TABLE . '"?#i', 'CREATE TEMPORARY TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp', $row['sql'])); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . '_temp SELECT * FROM ' . PROFILE_FIELDS_DATA_TABLE); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE); + + preg_match('#\((.*)\)#s', $row['sql'], $matches); + + $new_table_cols = trim($matches[1]); + $old_table_cols = explode(',', $new_table_cols); + $column_list = array(); + + foreach ($old_table_cols as $declaration) + { + $entities = preg_split('#\s+#', trim($declaration)); + if ($entities[0] == 'PRIMARY') + { + continue; + } + $column_list[] = $entities[0]; + } + + $columns = implode(',', $column_list); + + $new_table_cols = $field_ident . ' ' . $type . ',' . $new_table_cols; + + // create a new table and fill it up. destroy the temp one + $db->sql_query('CREATE TABLE ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $new_table_cols . ');'); + $db->sql_query('INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . PROFILE_FIELDS_DATA_TABLE . '_temp;'); + $db->sql_query('DROP TABLE ' . PROFILE_FIELDS_DATA_TABLE . '_temp'); + } + else + { + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident [$type]"; + } + + break; + + case 'mssql': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE [' . PROFILE_FIELDS_DATA_TABLE . "] ADD [$field_ident] "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' [VARCHAR] (255) '; + break; + + case FIELD_DATE: + $sql .= '[VARCHAR] (10) '; + break; + + case FIELD_TEXT: + $sql .= "[TEXT]"; + // ADD {$field_ident}_bbcode_uid [VARCHAR] (5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield [INT] UNSIGNED"; + break; + + case FIELD_BOOL: + case FIELD_DROPDOWN: + $sql .= '[INT] '; + break; + + case FIELD_INT: + $sql .= '[FLOAT] '; + break; + } + + break; + + case 'postgres': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD COLUMN \"$field_ident\" "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INT4 UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'INT2 '; + break; + + case FIELD_DROPDOWN: + $sql .= 'INT4 '; + break; + + case FIELD_INT: + $sql .= 'INT8 '; + break; + } + + break; + + case 'firebird': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD \"$field_ident\" "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "BLOB SUB_TYPE TEXT"; + // ADD {$field_ident}_bbcode_uid VARCHAR(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield INTEGER UNSIGNED"; + break; + + case FIELD_BOOL: + case FIELD_DROPDOWN: + $sql .= 'INTEGER '; + break; + + case FIELD_INT: + $sql .= 'DOUBLE PRECISION '; + break; + } + + break; + + case 'oracle': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD $field_ident "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR2(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR2(10) '; + break; + + case FIELD_TEXT: + $sql .= "CLOB"; + // ADD {$field_ident}_bbcode_uid VARCHAR2(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield NUMBER(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'NUMBER(2) '; + break; + + case FIELD_DROPDOWN: + $sql .= 'NUMBER(8) '; + break; + + case FIELD_INT: + $sql .= 'NUMBER(20) '; + break; + } + + break; + + case 'db2': + + // We are defining the biggest common value, because of the possibility to edit the min/max values of each field. + $sql = 'ALTER TABLE ' . PROFILE_FIELDS_DATA_TABLE . " ADD \"$field_ident\" "; + + switch ($field_type) + { + case FIELD_STRING: + $sql .= ' VARCHAR(255) '; + break; + + case FIELD_DATE: + $sql .= 'VARCHAR(10) '; + break; + + case FIELD_TEXT: + $sql .= "varchar(32672)"; + // ADD {$field_ident}_bbcode_uid VARCHAR2(5) NOT NULL, + // ADD {$field_ident}_bbcode_bitfield NUMBER(11) UNSIGNED"; + break; + + case FIELD_BOOL: + $sql .= 'smallint '; + break; + + case FIELD_DROPDOWN: + $sql .= 'integer '; + break; + + case FIELD_INT: + $sql .= 'float '; + break; + } + + break; + } + + return $sql; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_prune.php b/phpBB/modules/acp/acp_prune.php new file mode 100644 index 0000000000..ba49efff1a --- /dev/null +++ b/phpBB/modules/acp/acp_prune.php @@ -0,0 +1,459 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_prune +{ + var $u_action; + + function main($id, $mode) + { + global $user; + + $user->add_lang('acp/prune'); + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + switch ($mode) + { + case 'forums': + $this->tpl_name = 'acp_prune_forums'; + $this->page_title = 'ACP_PRUNE_FORUMS'; + $this->prune_forums($id, $mode); + break; + + case 'users': + $this->tpl_name = 'acp_prune_users'; + $this->page_title = 'ACP_PRUNE_USERS'; + $this->prune_users($id, $mode); + break; + } + } + + /** + * Prune forums + */ + function prune_forums($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $all_forums = request_var('all_forums', 0); + $forum_id = request_var('f', array(0)); + $submit = request::is_set_post('submit'); + + if ($all_forums) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + $forum_id = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_id[] = $row['forum_id']; + } + $db->sql_freeresult($result); + } + + if ($submit) + { + if (confirm_box(true)) + { + $prune_posted = request_var('prune_days', 0); + $prune_viewed = request_var('prune_vieweddays', 0); + $prune_all = (!$prune_posted && !$prune_viewed) ? true : false; + + $prune_flags = 0; + $prune_flags += (request_var('prune_old_polls', 0)) ? 2 : 0; + $prune_flags += (request_var('prune_announce', 0)) ? 4 : 0; + $prune_flags += (request_var('prune_sticky', 0)) ? 8 : 0; + + // Convert days to seconds for timestamp functions... + $prunedate_posted = time() - ($prune_posted * 86400); + $prunedate_viewed = time() - ($prune_viewed * 86400); + + $template->assign_vars(array( + 'S_PRUNED' => true) + ); + + $sql_forum = (sizeof($forum_id)) ? ' AND ' . $db->sql_in_set('forum_id', $forum_id) : ''; + + // Get a list of forum's or the data for the forum that we are pruning. + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST . " + $sql_forum + ORDER BY left_id ASC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $prune_ids = array(); + $p_result['topics'] = 0; + $p_result['posts'] = 0; + $log_data = ''; + + do + { + if (!$auth->acl_get('f_list', $row['forum_id'])) + { + continue; + } + + if ($prune_all) + { + $p_result = prune($row['forum_id'], 'posted', time(), $prune_flags, false); + } + else + { + if ($prune_posted) + { + $return = prune($row['forum_id'], 'posted', $prunedate_posted, $prune_flags, false); + $p_result['topics'] += $return['topics']; + $p_result['posts'] += $return['posts']; + } + + if ($prune_viewed) + { + $return = prune($row['forum_id'], 'viewed', $prunedate_viewed, $prune_flags, false); + $p_result['topics'] += $return['topics']; + $p_result['posts'] += $return['posts']; + } + } + + $prune_ids[] = $row['forum_id']; + + $template->assign_block_vars('pruned', array( + 'FORUM_NAME' => $row['forum_name'], + 'NUM_TOPICS' => $p_result['topics'], + 'NUM_POSTS' => $p_result['posts']) + ); + + $log_data .= (($log_data != '') ? ', ' : '') . $row['forum_name']; + } + while ($row = $db->sql_fetchrow($result)); + + // Sync all pruned forums at once + sync('forum', 'forum_id', $prune_ids, true, true); + add_log('admin', 'LOG_PRUNE', $log_data); + } + $db->sql_freeresult($result); + + return; + } + else + { + confirm_box(false, $user->lang['PRUNE_FORUM_CONFIRM'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'submit' => 1, + 'all_forums' => $all_forums, + 'f' => $forum_id, + + 'prune_days' => request_var('prune_days', 0), + 'prune_vieweddays' => request_var('prune_vieweddays', 0), + 'prune_old_polls' => request_var('prune_old_polls', 0), + 'prune_announce' => request_var('prune_announce', 0), + 'prune_sticky' => request_var('prune_sticky', 0), + ))); + } + } + + // If they haven't selected a forum for pruning yet then + // display a select box to use for pruning. + if (!sizeof($forum_id)) + { + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_SELECT_FORUM' => true, + 'S_FORUM_OPTIONS' => make_forum_select(false, false, false)) + ); + } + else + { + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_id); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + if (!$row) + { + $db->sql_freeresult($result); + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $forum_list = $s_hidden_fields = ''; + do + { + $forum_list .= (($forum_list != '') ? ', ' : '') . '<b>' . $row['forum_name'] . '</b>'; + $s_hidden_fields .= '<input type="hidden" name="f[]" value="' . $row['forum_id'] . '" />'; + } + while ($row = $db->sql_fetchrow($result)); + + $db->sql_freeresult($result); + + $l_selected_forums = (sizeof($forum_id) == 1) ? 'SELECTED_FORUM' : 'SELECTED_FORUMS'; + + $template->assign_vars(array( + 'L_SELECTED_FORUMS' => $user->lang[$l_selected_forums], + 'U_ACTION' => $this->u_action, + 'U_BACK' => $this->u_action, + 'FORUM_LIST' => $forum_list, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + } + } + + /** + * Prune users + */ + function prune_users($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('memberlist'); + + $prune = request::is_set_post('prune'); + + if ($prune) + { + $action = request_var('action', 'deactivate'); + $deleteposts = request_var('deleteposts', 0); + + if (confirm_box(true)) + { + $user_ids = $usernames = array(); + $this->get_prune_users($user_ids, $usernames); + + if (sizeof($user_ids)) + { + if ($action == 'deactivate') + { + user_active_flip('deactivate', $user_ids); + $l_log = 'LOG_PRUNE_USER_DEAC'; + } + else if ($action == 'delete') + { + if ($deleteposts) + { + foreach ($user_ids as $user_id) + { + user_delete('remove', $user_id); + } + + $l_log = 'LOG_PRUNE_USER_DEL_DEL'; + } + else + { + foreach ($user_ids as $user_id) + { + user_delete('retain', $user_id, $usernames[$user_id]); + } + + $l_log = 'LOG_PRUNE_USER_DEL_ANON'; + } + } + + add_log('admin', $l_log, implode(', ', $usernames)); + $msg = $user->lang['USER_' . strtoupper($action) . '_SUCCESS']; + } + else + { + $msg = $user->lang['USER_PRUNE_FAILURE']; + } + + trigger_error($msg . adm_back_link($this->u_action)); + } + else + { + // We list the users which will be pruned... + $user_ids = $usernames = array(); + $this->get_prune_users($user_ids, $usernames); + + if (!sizeof($user_ids)) + { + trigger_error($user->lang['USER_PRUNE_FAILURE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Assign to template + foreach ($user_ids as $user_id) + { + $template->assign_block_vars('users', array( + 'USERNAME' => $usernames[$user_id], + 'U_PROFILE' => append_sid('memberlist', 'mode=viewprofile&u=' . $user_id), + 'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=users&mode=overview&u=' . $user_id, true, $user->session_id) : '', + )); + } + + $template->assign_vars(array( + 'S_DEACTIVATE' => ($action == 'deactivate') ? true : false, + 'S_DELETE' => ($action == 'delete') ? true : false, + )); + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'prune' => 1, + + 'users' => request_var('users', '', true), + 'username' => request_var('username', '', true), + 'email' => request_var('email', ''), + 'joined_select' => request_var('joined_select', ''), + 'joined' => request_var('joined', ''), + 'active_select' => request_var('active_select', ''), + 'active' => request_var('active', ''), + 'count_select' => request_var('count_select', ''), + 'count' => request_var('count', ''), + 'deleteposts' => request_var('deleteposts', 0), + + 'action' => request_var('action', ''), + )), 'confirm_body_prune.html'); + } + } + + $find_count = array('lt' => $user->lang['LESS_THAN'], 'eq' => $user->lang['EQUAL_TO'], 'gt' => $user->lang['MORE_THAN']); + $s_find_count = ''; + + foreach ($find_count as $key => $value) + { + $selected = ($key == 'eq') ? ' selected="selected"' : ''; + $s_find_count .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $find_time = array('lt' => $user->lang['BEFORE'], 'gt' => $user->lang['AFTER']); + $s_find_join_time = ''; + foreach ($find_time as $key => $value) + { + $s_find_join_time .= '<option value="' . $key . '">' . $value . '</option>'; + } + + $s_find_active_time = ''; + foreach ($find_time as $key => $value) + { + $s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>'; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_JOINED_OPTIONS' => $s_find_join_time, + 'S_ACTIVE_OPTIONS' => $s_find_active_time, + 'S_COUNT_OPTIONS' => $s_find_count, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=acp_prune&field=users'), + )); + } + + /** + * Get user_ids/usernames from those being pruned + */ + function get_prune_users(&$user_ids, &$usernames) + { + global $user, $db; + + $users = request_var('users', '', true); + + if ($users) + { + $users = explode("\n", $users); + $where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users)); + } + else + { + $username = request_var('username', '', true); + $email = request_var('email', ''); + + $joined_select = request_var('joined_select', 'lt'); + $active_select = request_var('active_select', 'lt'); + $count_select = request_var('count_select', 'eq'); + $joined = request_var('joined', ''); + $active = request_var('active', ''); + + $active = ($active) ? explode('-', $active) : array(); + $joined = ($joined) ? explode('-', $joined) : array(); + + if ((sizeof($active) && sizeof($active) != 3) || (sizeof($joined) && sizeof($joined) != 3)) + { + trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $count = request_var('count', ''); + + $key_match = array('lt' => '<', 'gt' => '>', 'eq' => '='); + $sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit'); + + $where_sql = ''; + $where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : ''; + $where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : ''; + $where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : ''; + $where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : ''; + + if (sizeof($active) && $active_select != 'lt') + { + $where_sql .= ' AND user_lastvisit ' . $key_match[$active_select] . ' ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]); + } + else if (sizeof($active)) + { + $where_sql .= ' AND (user_lastvisit > 0 AND user_lastvisit < ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]) . ')'; + } + } + + // Protect the admin, do not prune if no options are given... + if (!$where_sql) + { + return; + } + + // Get bot ids + $sql = 'SELECT user_id + FROM ' . BOTS_TABLE; + $result = $db->sql_query($sql); + + $bot_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $bot_ids[] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Do not prune founder members + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE user_id <> ' . ANONYMOUS . ' + AND user_type <> ' . USER_FOUNDER . " + $where_sql"; + $result = $db->sql_query($sql); + + $where_sql = ''; + $user_ids = $usernames = array(); + + while ($row = $db->sql_fetchrow($result)) + { + // Do not prune bots and the user currently pruning. + if ($row['user_id'] != $user->data['user_id'] && !in_array($row['user_id'], $bot_ids)) + { + $user_ids[] = $row['user_id']; + $usernames[$row['user_id']] = $row['username']; + } + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_ranks.php b/phpBB/modules/acp/acp_ranks.php new file mode 100644 index 0000000000..08d6cf5c8c --- /dev/null +++ b/phpBB/modules/acp/acp_ranks.php @@ -0,0 +1,242 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_ranks +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (request::is_set_post('add')) ? 'add' : $action; + $action = (request::is_set_post('save')) ? 'save' : $action; + $rank_id = request_var('id', 0); + + $this->tpl_name = 'acp_ranks'; + $this->page_title = 'ACP_MANAGE_RANKS'; + + $form_name = 'acp_prune'; + add_form_key($form_name); + + switch ($action) + { + case 'save': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + $rank_title = utf8_normalize_nfc(request_var('title', '', true)); + $special_rank = request_var('special_rank', 0); + $min_posts = ($special_rank) ? 0 : request_var('min_posts', 0); + $rank_image = request_var('rank_image', ''); + + // The rank image has to be a jpg, gif or png + if ($rank_image != '' && !preg_match('#(\.gif|\.png|\.jpg|\.jpeg)$#i', $rank_image)) + { + $rank_image = ''; + } + + if (!$rank_title) + { + trigger_error($user->lang['NO_RANK_TITLE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'rank_title' => $rank_title, + 'rank_special' => $special_rank, + 'rank_min' => $min_posts, + 'rank_image' => htmlspecialchars_decode($rank_image) + ); + + if ($rank_id) + { + $sql = 'UPDATE ' . RANKS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " WHERE rank_id = $rank_id"; + $message = $user->lang['RANK_UPDATED']; + + add_log('admin', 'LOG_RANK_UPDATED', $rank_title); + } + else + { + $sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $message = $user->lang['RANK_ADDED']; + + add_log('admin', 'LOG_RANK_ADDED', $rank_title); + } + $db->sql_query($sql); + + $cache->destroy('_ranks'); + + trigger_error($message . adm_back_link($this->u_action)); + + break; + + case 'delete': + + if (!$rank_id) + { + trigger_error($user->lang['MUST_SELECT_RANK'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT rank_title + FROM ' . RANKS_TABLE . ' + WHERE rank_id = ' . $rank_id; + $result = $db->sql_query($sql); + $rank_title = (string) $db->sql_fetchfield('rank_title'); + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . RANKS_TABLE . " + WHERE rank_id = $rank_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_rank = 0 + WHERE user_rank = $rank_id"; + $db->sql_query($sql); + + $cache->destroy('_ranks'); + + add_log('admin', 'LOG_RANK_REMOVED', $rank_title); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'rank_id' => $rank_id, + 'action' => 'delete', + ))); + } + + break; + + case 'edit': + case 'add': + + $data = $ranks = $existing_imgs = array(); + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + ORDER BY rank_min ASC, rank_special ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $existing_imgs[] = $row['rank_image']; + + if ($action == 'edit' && $rank_id == $row['rank_id']) + { + $ranks = $row; + } + } + $db->sql_freeresult($result); + + $imglist = filelist(PHPBB_ROOT_PATH . $config['ranks_path'], ''); + $edit_img = $filename_list = ''; + + foreach ($imglist as $path => $img_ary) + { + sort($img_ary); + + foreach ($img_ary as $img) + { + $img = $path . $img; + + if (!in_array($img, $existing_imgs) || $action == 'edit') + { + if ($ranks && $img == $ranks['rank_image']) + { + $selected = ' selected="selected"'; + $edit_img = $img; + } + else + { + $selected = ''; + } + + if (strlen($img) > 255) + { + continue; + } + + $filename_list .= '<option value="' . htmlspecialchars($img) . '"' . $selected . '>' . $img . '</option>'; + } + } + } + + $filename_list = '<option value=""' . (($edit_img == '') ? ' selected="selected"' : '') . '>----------</option>' . $filename_list; + unset($existing_imgs, $imglist); + + $template->assign_vars(array( + 'S_EDIT' => true, + 'U_BACK' => $this->u_action, + 'RANKS_PATH' => PHPBB_ROOT_PATH . $config['ranks_path'], + 'U_ACTION' => $this->u_action . '&id=' . $rank_id, + + 'RANK_TITLE' => (isset($ranks['rank_title'])) ? $ranks['rank_title'] : '', + 'S_FILENAME_LIST' => $filename_list, + 'RANK_IMAGE' => ($edit_img) ? PHPBB_ROOT_PATH . $config['ranks_path'] . '/' . $edit_img : PHPBB_ADMIN_PATH . 'images/spacer.gif', + 'S_SPECIAL_RANK' => (!isset($ranks['rank_special']) || $ranks['rank_special']) ? true : false, + 'MIN_POSTS' => (isset($ranks['rank_min']) && !$ranks['rank_special']) ? $ranks['rank_min'] : 0) + ); + + + return; + + break; + } + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action) + ); + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + ORDER BY rank_special DESC, rank_min ASC, rank_title ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('ranks', array( + 'S_RANK_IMAGE' => ($row['rank_image']) ? true : false, + 'S_SPECIAL_RANK' => ($row['rank_special']) ? true : false, + + 'RANK_IMAGE' => PHPBB_ROOT_PATH . $config['ranks_path'] . '/' . $row['rank_image'], + 'RANK_TITLE' => $row['rank_title'], + 'MIN_POSTS' => $row['rank_min'], + + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['rank_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['rank_id']) + ); + } + $db->sql_freeresult($result); + + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_reasons.php b/phpBB/modules/acp/acp_reasons.php new file mode 100644 index 0000000000..a8d7c1f752 --- /dev/null +++ b/phpBB/modules/acp/acp_reasons.php @@ -0,0 +1,342 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_reasons +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang(array('mcp', 'acp/posting')); + + // Set up general vars + $action = request_var('action', ''); + $submit = request::is_set_post('submit'); + $reason_id = request_var('id', 0); + + $this->tpl_name = 'acp_reasons'; + $this->page_title = 'ACP_REASONS'; + + $form_name = 'acp_reason'; + add_form_key('acp_reason'); + + $error = array(); + + switch ($action) + { + case 'add': + case 'edit': + + $reason_row = array( + 'reason_title' => utf8_normalize_nfc(request_var('reason_title', '', true)), + 'reason_description' => utf8_normalize_nfc(request_var('reason_description', '', true)), + ); + + if ($submit) + { + if (!check_form_key($form_name)) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Reason specified? + if (!$reason_row['reason_title'] || !$reason_row['reason_description']) + { + $error[] = $user->lang['NO_REASON_INFO']; + } + + $check_double = ($action == 'add') ? true : false; + + if ($action == 'edit') + { + $sql = 'SELECT reason_title + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (strtolower($row['reason_title']) == 'other' || strtolower($reason_row['reason_title']) == 'other') + { + $reason_row['reason_title'] = 'other'; + } + + if ($row['reason_title'] != $reason_row['reason_title']) + { + $check_double = true; + } + } + + // Check for same reason if adding it... + if ($check_double) + { + $sql = 'SELECT reason_id + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_title = '" . $db->sql_escape($reason_row['reason_title']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row || ($action == 'add' && strtolower($reason_row['reason_title']) == 'other')) + { + $error[] = $user->lang['REASON_ALREADY_EXIST']; + } + } + + if (!sizeof($error)) + { + // New reason? + if ($action == 'add') + { + // Get new order... + $sql = 'SELECT MAX(reason_order) as max_reason_order + FROM ' . REPORTS_REASONS_TABLE; + $result = $db->sql_query($sql); + $max_order = (int) $db->sql_fetchfield('max_reason_order'); + $db->sql_freeresult($result); + + $sql_ary = array( + 'reason_title' => (string) $reason_row['reason_title'], + 'reason_description' => (string) $reason_row['reason_description'], + 'reason_order' => $max_order + 1 + ); + + $db->sql_query('INSERT INTO ' . REPORTS_REASONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $log = 'ADDED'; + } + else if ($reason_id) + { + $sql_ary = array( + 'reason_title' => (string) $reason_row['reason_title'], + 'reason_description' => (string) $reason_row['reason_description'], + ); + + $db->sql_query('UPDATE ' . REPORTS_REASONS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE reason_id = ' . $reason_id); + + $log = 'UPDATED'; + } + + add_log('admin', 'LOG_REASON_' . $log, $reason_row['reason_title']); + trigger_error($user->lang['REASON_' . $log] . adm_back_link($this->u_action)); + } + } + else if ($reason_id) + { + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + WHERE reason_id = ' . $reason_id; + $result = $db->sql_query($sql); + $reason_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$reason_row) + { + trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + $l_title = ($action == 'edit') ? 'EDIT' : 'ADD'; + + $translated = false; + + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])])) + { + $translated = true; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['REASON_' . $l_title], + 'U_ACTION' => $this->u_action . "&id=$reason_id&action=$action", + 'U_BACK' => $this->u_action, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'REASON_TITLE' => $reason_row['reason_title'], + 'REASON_DESCRIPTION' => $reason_row['reason_description'], + + 'TRANSLATED_TITLE' => ($translated) ? $user->lang['report_reasons']['TITLE'][strtoupper($reason_row['reason_title'])] : '', + 'TRANSLATED_DESCRIPTION'=> ($translated) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason_row['reason_title'])] : '', + + 'S_AVAILABLE_TITLES' => implode(', ', array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))), + 'S_EDIT_REASON' => true, + 'S_TRANSLATED' => $translated, + 'S_ERROR' => (sizeof($error)) ? true : false, + ) + ); + + return; + break; + + case 'delete': + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + WHERE reason_id = ' . $reason_id; + $result = $db->sql_query($sql); + $reason_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$reason_row) + { + trigger_error($user->lang['NO_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (strtolower($reason_row['reason_title']) == 'other') + { + trigger_error($user->lang['NO_REMOVE_DEFAULT_REASON'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Let the deletion be confirmed... + if (confirm_box(true)) + { + $sql = 'SELECT reason_id, report_text + FROM ' . REPORTS_REASONS_TABLE . " + WHERE LOWER(reason_title) = 'other'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + + $other_reason_id = (int) $row['reason_id']; + $report_text = $row['report_text']; + + $db->sql_freeresult($result); + + $report_text .= $reason_row['reason_description'] . "\n\n"; + + $sql = 'UPDATE ' . REPORTS_TABLE . ' + SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($report_text) . "' + WHERE reason_id = $reason_id"; + $db->sql_query($sql); + + $db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id); + + add_log('admin', 'LOG_REASON_REMOVED', $reason_row['reason_title']); + trigger_error($user->lang['REASON_REMOVED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $reason_id)) + ); + } + + break; + + case 'move_up': + case 'move_down': + + $order = request_var('order', 0); + $order_total = $order * 2 + (($action == 'move_up') ? -1 : 1); + + $sql = 'UPDATE ' . REPORTS_REASONS_TABLE . ' + SET reason_order = ' . $order_total . ' - reason_order + WHERE reason_order IN (' . $order . ', ' . (($action == 'move_up') ? $order - 1 : $order + 1) . ')'; + $db->sql_query($sql); + + break; + } + + // By default, check that order is valid and fix it if necessary + $sql = 'SELECT reason_id, reason_order + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order'; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $order = 0; + do + { + ++$order; + + if ($row['reason_order'] != $order) + { + $sql = 'UPDATE ' . REPORTS_REASONS_TABLE . " + SET reason_order = $order + WHERE reason_id = {$row['reason_id']}"; + $db->sql_query($sql); + } + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + ) + ); + + // Reason count + $sql = 'SELECT reason_id, COUNT(reason_id) AS reason_count + FROM ' . REPORTS_TABLE . ' + GROUP BY reason_id'; + $result = $db->sql_query($sql); + + $reason_count = array(); + while ($row = $db->sql_fetchrow($result)) + { + $reason_count[$row['reason_id']] = $row['reason_count']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT * + FROM ' . REPORTS_REASONS_TABLE . ' + ORDER BY reason_order ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $translated = false; + $other_reason = ($row['reason_title'] == 'other') ? true : false; + + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reason_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + + $translated = true; + } + + $template->assign_block_vars('reasons', array( + 'REASON_TITLE' => $row['reason_title'], + 'REASON_DESCRIPTION' => $row['reason_description'], + 'REASON_COUNT' => (isset($reason_count[$row['reason_id']])) ? $reason_count[$row['reason_id']] : 0, + + 'S_TRANSLATED' => $translated, + 'S_OTHER_REASON' => $other_reason, + + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['reason_id'], + 'U_DELETE' => (!$other_reason) ? $this->u_action . '&action=delete&id=' . $row['reason_id'] : '', + 'U_MOVE_UP' => $this->u_action . '&action=move_up&order=' . $row['reason_order'], + 'U_MOVE_DOWN' => $this->u_action . '&action=move_down&order=' . $row['reason_order']) + ); + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_search.php b/phpBB/modules/acp/acp_search.php new file mode 100644 index 0000000000..6f38a95bff --- /dev/null +++ b/phpBB/modules/acp/acp_search.php @@ -0,0 +1,623 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_search +{ + var $u_action; + var $state; + var $search; + var $max_post_id; + var $batch_size = 100; + + function main($id, $mode) + { + global $user; + + $user->add_lang('acp/search'); + + // For some this may be of help... + @ini_set('memory_limit', '128M'); + + switch ($mode) + { + case 'settings': + $this->settings($id, $mode); + break; + + case 'index': + $this->index($id, $mode); + break; + } + } + + function settings($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $submit = request::is_set_post('submit'); + + $search_types = $this->get_search_types(); + + $settings = array( + 'search_interval' => 'float', + 'search_anonymous_interval' => 'float', + 'load_search' => 'bool', + 'limit_search_load' => 'float', + 'min_search_author_chars' => 'integer', + 'search_store_results' => 'integer', + ); + + $search = null; + $error = false; + $search_options = ''; + foreach ($search_types as $type) + { + if ($this->init_search($type, $search, $error)) + { + continue; + } + + $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + $selected = ($config['search_type'] == $type) ? ' selected="selected"' : ''; + $search_options .= '<option value="' . $type . '"' . $selected . '>' . $name . '</option>'; + + if (method_exists($search, 'acp')) + { + $vars = $search->acp(); + + if (!$submit) + { + $template->assign_block_vars('backend', array( + 'NAME' => $name, + 'SETTINGS' => $vars['tpl']) + ); + } + else if (is_array($vars['config'])) + { + $settings = array_merge($settings, $vars['config']); + } + } + } + unset($search); + unset($error); + + $cfg_array = request_var('config', array('' => ''), true); + $updated = request_var('updated', false); + + foreach ($settings as $config_name => $var_type) + { + if (!isset($cfg_array[$config_name])) + { + continue; + } + + // e.g. integer:4:12 (min 4, max 12) + $var_type = explode(':', $var_type); + + $config_value = $cfg_array[$config_name]; + settype($config_value, $var_type[0]); + + if (isset($var_type[1])) + { + $config_value = max($var_type[1], $config_value); + } + + if (isset($var_type[2])) + { + $config_value = min($var_type[2], $config_value); + } + + // only change config if anything was actually changed + if ($submit && ($config[$config_name] != $config_value)) + { + set_config($config_name, $config_value); + $updated = true; + } + } + + if ($submit) + { + $extra_message = ''; + if ($updated) + { + add_log('admin', 'LOG_CONFIG_SEARCH'); + } + + if (isset($cfg_array['search_type']) && in_array($cfg_array['search_type'], $search_types, true) && ($cfg_array['search_type'] != $config['search_type'])) + { + $search = null; + $error = false; + + if (!$this->init_search($cfg_array['search_type'], $search, $error)) + { + if (confirm_box(true)) + { + if (!method_exists($search, 'init') || !($error = $search->init())) + { + set_config('search_type', $cfg_array['search_type']); + + if (!$updated) + { + add_log('admin', 'LOG_CONFIG_SEARCH'); + } + $extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=search&mode=index') . '">» ' . $user->lang['GO_TO_SEARCH_INDEX'] . '</a>'; + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_SEARCH_BACKEND'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'submit' => true, + 'updated' => $updated, + 'config' => array('search_type' => $cfg_array['search_type']), + ))); + } + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + $search = null; + $error = false; + if (!$this->init_search($config['search_type'], $search, $error)) + { + if ($updated) + { + if (method_exists($search, 'config_updated')) + { + if ($search->config_updated()) + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + } + else + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + + trigger_error($user->lang['CONFIG_UPDATED'] . $extra_message . adm_back_link($this->u_action)); + } + unset($cfg_array); + + $this->tpl_name = 'acp_search'; + $this->page_title = 'ACP_SEARCH_SETTINGS'; + + $template->assign_vars(array( + 'LIMIT_SEARCH_LOAD' => (float) $config['limit_search_load'], + 'MIN_SEARCH_AUTHOR_CHARS' => (int) $config['min_search_author_chars'], + 'SEARCH_INTERVAL' => (float) $config['search_interval'], + 'SEARCH_GUEST_INTERVAL' => (float) $config['search_anonymous_interval'], + 'SEARCH_STORE_RESULTS' => (int) $config['search_store_results'], + + 'S_SEARCH_TYPES' => $search_options, + 'S_YES_SEARCH' => (bool) $config['load_search'], + 'S_SETTINGS' => true, + + 'U_ACTION' => $this->u_action) + ); + } + + function index($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $action = request_var('action', array('' => false)); + if (sizeof($action)) + { + $action = key($action); + } + else + { + $action = request_var('action', ''); + } + $this->state = explode(',', $config['search_indexing_state']); + + if (request::is_set_post('cancel')) + { + $action = ''; + $this->state = array(); + $this->save_state(); + } + + if ($action) + { + switch ($action) + { + case 'progress_bar': + $type = request_var('type', ''); + $this->display_progress_bar($type); + break; + + case 'delete': + $this->state[1] = 'delete'; + break; + + case 'create': + $this->state[1] = 'create'; + break; + + default: + trigger_error('NO_ACTION', E_USER_ERROR); + break; + } + + if (empty($this->state[0])) + { + $this->state[0] = request_var('search_type', ''); + } + + $this->search = null; + $error = false; + if ($this->init_search($this->state[0], $this->search, $error)) + { + trigger_error($error . adm_back_link($this->u_action), E_USER_WARNING); + } + $name = ucfirst(strtolower(str_replace('_', ' ', $this->state[0]))); + + $action = &$this->state[1]; + + $this->max_post_id = $this->get_max_post_id(); + + $post_counter = (isset($this->state[2])) ? $this->state[2] : 0; + $this->state[2] = &$post_counter; + $this->save_state(); + + switch ($action) + { + case 'delete': + if (method_exists($this->search, 'delete_index')) + { + // pass a reference to myself so the $search object can make use of save_state() and attributes + if ($error = $this->search->delete_index($this, append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&mode=$mode&action=delete", false))) + { + $this->state = array(''); + $this->save_state(); + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + } + } + else + { + $starttime = explode(' ', microtime()); + $starttime = $starttime[1] + $starttime[0]; + $row_count = 0; + while (still_on_time() && $post_counter <= $this->max_post_id) + { + $sql = 'SELECT post_id, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $this->batch_size); + $result = $db->sql_query($sql); + + $ids = $posters = $forum_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $ids[] = $row['post_id']; + $posters[] = $row['poster_id']; + $forum_ids[] = $row['forum_id']; + } + $db->sql_freeresult($result); + $row_count += sizeof($ids); + + if (sizeof($ids)) + { + $this->search->index_remove($ids, $posters, $forum_ids); + } + + $post_counter += $this->batch_size; + } + // save the current state + $this->save_state(); + + if ($post_counter <= $this->max_post_id) + { + $mtime = explode(' ', microtime()); + $totaltime = $mtime[0] + $mtime[1] - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter)); + trigger_error(sprintf($user->lang['SEARCH_INDEX_DELETE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + } + } + + $this->search->tidy(); + + $this->state = array(''); + $this->save_state(); + + add_log('admin', 'LOG_SEARCH_INDEX_REMOVED', $name); + trigger_error($user->lang['SEARCH_INDEX_REMOVED'] . adm_back_link($this->u_action) . $this->close_popup_js()); + break; + + case 'create': + if (method_exists($this->search, 'create_index')) + { + // pass a reference to acp_search so the $search object can make use of save_state() and attributes + if ($error = $this->search->create_index($this, append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&mode=$mode&action=create", false))) + { + $this->state = array(''); + $this->save_state(); + trigger_error($error . adm_back_link($this->u_action) . $this->close_popup_js(), E_USER_WARNING); + } + } + else + { + $sql = 'SELECT forum_id, enable_indexing + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql, 3600); + + while ($row = $db->sql_fetchrow($result)) + { + $forums[$row['forum_id']] = (bool) $row['enable_indexing']; + } + $db->sql_freeresult($result); + + $starttime = explode(' ', microtime()); + $starttime = $starttime[1] + $starttime[0]; + $row_count = 0; + while (still_on_time() && $post_counter <= $this->max_post_id) + { + $sql = 'SELECT post_id, post_subject, post_text, poster_id, forum_id + FROM ' . POSTS_TABLE . ' + WHERE post_id >= ' . (int) ($post_counter + 1) . ' + AND post_id <= ' . (int) ($post_counter + $this->batch_size); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Indexing enabled for this forum or global announcement? + // Global announcements get indexed by default. + if (!$row['forum_id'] || (isset($forums[$row['forum_id']]) && $forums[$row['forum_id']])) + { + $this->search->index('post', $row['post_id'], $row['post_text'], $row['post_subject'], $row['poster_id'], $row['forum_id']); + } + $row_count++; + } + $db->sql_freeresult($result); + + $post_counter += $this->batch_size; + } + // save the current state + $this->save_state(); + + // pretend the number of posts was as big as the number of ids we indexed so far + // just an estimation as it includes deleted posts + $num_posts = $config['num_posts']; + $config['num_posts'] = min($config['num_posts'], $post_counter); + $this->search->tidy(); + $config['num_posts'] = $num_posts; + + if ($post_counter <= $this->max_post_id) + { + $mtime = explode(' ', microtime()); + $totaltime = $mtime[0] + $mtime[1] - $starttime; + $rows_per_second = $row_count / $totaltime; + meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter)); + trigger_error(sprintf($user->lang['SEARCH_INDEX_CREATE_REDIRECT'], $post_counter, $row_count, $rows_per_second)); + } + } + + $this->search->tidy(); + + $this->state = array(''); + $this->save_state(); + + add_log('admin', 'LOG_SEARCH_INDEX_CREATED', $name); + trigger_error($user->lang['SEARCH_INDEX_CREATED'] . adm_back_link($this->u_action) . $this->close_popup_js()); + break; + } + } + + $search_types = $this->get_search_types(); + + $search = null; + $error = false; + $search_options = ''; + foreach ($search_types as $type) + { + if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created')) + { + continue; + } + + $name = ucfirst(strtolower(str_replace('_', ' ', $type))); + + $data = array(); + if (method_exists($search, 'index_stats')) + { + $data = $search->index_stats(); + } + + $statistics = array(); + foreach ($data as $statistic => $value) + { + $n = sizeof($statistics); + if ($n && sizeof($statistics[$n - 1]) < 3) + { + $statistics[$n - 1] += array('statistic_2' => $statistic, 'value_2' => $value); + } + else + { + $statistics[] = array('statistic_1' => $statistic, 'value_1' => $value); + } + } + + $template->assign_block_vars('backend', array( + 'L_NAME' => $name, + 'NAME' => $type, + + 'S_ACTIVE' => ($type == $config['search_type']) ? true : false, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('search_type' => $type)), + 'S_INDEXED' => (bool) $search->index_created(), + 'S_STATS' => (bool) sizeof($statistics)) + ); + + foreach ($statistics as $statistic) + { + $template->assign_block_vars('backend.data', array( + 'STATISTIC_1' => $statistic['statistic_1'], + 'VALUE_1' => $statistic['value_1'], + 'STATISTIC_2' => (isset($statistic['statistic_2'])) ? $statistic['statistic_2'] : '', + 'VALUE_2' => (isset($statistic['value_2'])) ? $statistic['value_2'] : '') + ); + } + } + unset($search); + unset($error); + unset($statistics); + unset($data); + + $this->tpl_name = 'acp_search'; + $this->page_title = 'ACP_SEARCH_INDEX'; + + $template->assign_vars(array( + 'S_INDEX' => true, + 'U_ACTION' => $this->u_action, + 'U_PROGRESS_BAR' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&mode=$mode&action=progress_bar"), + 'UA_PROGRESS_BAR' => addslashes(append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&mode=$mode&action=progress_bar")), + )); + + if (isset($this->state[1])) + { + $template->assign_vars(array( + 'S_CONTINUE_INDEXING' => $this->state[1], + 'U_CONTINUE_INDEXING' => $this->u_action . '&action=' . $this->state[1], + 'L_CONTINUE' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING'] : $user->lang['CONTINUE_DELETING_INDEX'], + 'L_CONTINUE_EXPLAIN' => ($this->state[1] == 'create') ? $user->lang['CONTINUE_INDEXING_EXPLAIN'] : $user->lang['CONTINUE_DELETING_INDEX_EXPLAIN']) + ); + } + } + + function display_progress_bar($type) + { + global $template, $user; + + $l_type = ($type == 'create') ? 'INDEXING_IN_PROGRESS' : 'DELETING_INDEX_IN_PROGRESS'; + + adm_page_header($user->lang[$l_type]); + + $template->set_filenames(array( + 'body' => 'progress_bar.html') + ); + + $template->assign_vars(array( + 'L_PROGRESS' => $user->lang[$l_type], + 'L_PROGRESS_EXPLAIN' => $user->lang[$l_type . '_EXPLAIN']) + ); + + adm_page_footer(); + } + + function close_popup_js() + { + return "<script type=\"text/javascript\">\n" . + "// <![CDATA[\n" . + " close_waitscreen = 1;\n" . + "// ]]>\n" . + "</script>\n"; + } + + function get_search_types() + { + $search_types = array(); + + $dp = @opendir(PHPBB_ROOT_PATH . 'includes/search'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ((preg_match('#\.' . PHP_EXT . '$#', $file)) && ($file != 'search.' . PHP_EXT)) + { + $search_types[] = preg_replace('#^(.*?)\.' . PHP_EXT . '$#', '\1', $file); + } + } + closedir($dp); + + sort($search_types); + } + + return $search_types; + } + + function get_max_post_id() + { + global $db; + + $sql = 'SELECT MAX(post_id) as max_post_id + FROM '. POSTS_TABLE; + $result = $db->sql_query($sql); + $max_post_id = (int) $db->sql_fetchfield('max_post_id'); + $db->sql_freeresult($result); + + return $max_post_id; + } + + function save_state($state = false) + { + if ($state) + { + $this->state = $state; + } + + ksort($this->state); + + set_config('search_indexing_state', implode(',', $this->state)); + } + + /** + * Initialises a search backend object + * + * @return false if no error occurred else an error message + */ + function init_search($type, &$search, &$error) + { + global $user; + + if (!preg_match('#^\w+$#', $type) || !file_exists(PHPBB_ROOT_PATH . "includes/search/$type." . PHP_EXT)) + { + $error = $user->lang['NO_SUCH_SEARCH_MODULE']; + return $error; + } + + include_once(PHPBB_ROOT_PATH . "includes/search/$type." . PHP_EXT); + + if (!class_exists($type)) + { + $error = $user->lang['NO_SUCH_SEARCH_MODULE']; + return $error; + } + + $error = false; + $search = new $type($error); + + return $error; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_styles.php b/phpBB/modules/acp/acp_styles.php new file mode 100644 index 0000000000..03abe01dbc --- /dev/null +++ b/phpBB/modules/acp/acp_styles.php @@ -0,0 +1,3071 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_styles +{ + var $u_action; + + var $style_cfg; + var $template_cfg; + var $theme_cfg; + var $imageset_cfg; + var $imageset_keys; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + // Hardcoded template bitfield to add for new templates + $bitfield = new bitfield(); + $bitfield->set(0); + $bitfield->set(3); + $bitfield->set(8); + $bitfield->set(9); + $bitfield->set(11); + $bitfield->set(12); + define('TEMPLATE_BITFIELD', $bitfield->get_base64()); + unset($bitfield); + + $user->add_lang('acp/styles'); + + $this->tpl_name = 'acp_styles'; + $this->page_title = 'ACP_CAT_STYLES'; + + $action = request_var('action', ''); + $action = (request::is_set_post('add')) ? 'add' : $action; + $style_id = request_var('id', 0); + + // Fill the configuration variables + $this->style_cfg = $this->template_cfg = $this->theme_cfg = $this->imageset_cfg = ' +# +# phpBB {MODE} configuration file +# +# @package phpBB3 +# @copyright (c) 2005 phpBB Group +# @license http://opensource.org/licenses/gpl-license.php GNU Public License +# +# +# At the left is the name, please do not change this +# At the right the value is entered +# For on/off options the valid values are on, off, 1, 0, true and false +# +# Values get trimmed, if you want to add a space in front or at the end of +# the value, then enclose the value with single or double quotes. +# Single and double quotes do not need to be escaped. +# +# + +# General Information about this {MODE} +name = {NAME} +copyright = {COPYRIGHT} +version = {VERSION} +'; + + $this->theme_cfg .= ' +# Some configuration options + +# +# You have to turn this option on if you want to use the +# path template variables ({T_IMAGESET_PATH} for example) within +# your css file. +# This is mostly the case if you want to use language specific +# images within your css file. +# +parse_css_file = {PARSE_CSS_FILE} +'; + + $this->imageset_keys = array( + 'logos' => array( + 'site_logo', + ), + 'buttons' => array( + 'icon_back_top', 'icon_contact_aim', 'icon_contact_email', 'icon_contact_icq', 'icon_contact_jabber', 'icon_contact_msnm', 'icon_contact_pm', 'icon_contact_yahoo', 'icon_contact_www', 'icon_post_delete', 'icon_post_edit', 'icon_post_info', 'icon_post_quote', 'icon_post_report', 'icon_user_online', 'icon_user_offline', 'icon_user_profile', 'icon_user_search', 'icon_user_warn', 'button_pm_forward', 'button_pm_new', 'button_pm_reply', 'button_topic_locked', 'button_topic_new', 'button_topic_reply', + ), + 'icons' => array( + 'icon_post_target', 'icon_post_target_unread', 'icon_topic_attach', 'icon_topic_latest', 'icon_topic_newest', 'icon_topic_reported', 'icon_topic_unapproved', 'icon_friend', 'icon_foe', + ), + 'forums' => array( + 'forum_link', 'forum_read', 'forum_read_locked', 'forum_read_subforum', 'forum_unread', 'forum_unread_locked', 'forum_unread_subforum', 'subforum_read', 'subforum_unread' + ), + 'folders' => array( + 'topic_moved', 'topic_read', 'topic_read_mine', 'topic_read_hot', 'topic_read_hot_mine', 'topic_read_locked', 'topic_read_locked_mine', 'topic_unread', 'topic_unread_mine', 'topic_unread_hot', 'topic_unread_hot_mine', 'topic_unread_locked', 'topic_unread_locked_mine', 'sticky_read', 'sticky_read_mine', 'sticky_read_locked', 'sticky_read_locked_mine', 'sticky_unread', 'sticky_unread_mine', 'sticky_unread_locked', 'sticky_unread_locked_mine', 'announce_read', 'announce_read_mine', 'announce_read_locked', 'announce_read_locked_mine', 'announce_unread', 'announce_unread_mine', 'announce_unread_locked', 'announce_unread_locked_mine', 'global_read', 'global_read_mine', 'global_read_locked', 'global_read_locked_mine', 'global_unread', 'global_unread_mine', 'global_unread_locked', 'global_unread_locked_mine', 'pm_read', 'pm_unread', + ), + 'polls' => array( + 'poll_left', 'poll_center', 'poll_right', + ), + 'ui' => array( + 'upload_bar', + ), + 'user' => array( + 'user_icon1', 'user_icon2', 'user_icon3', 'user_icon4', 'user_icon5', 'user_icon6', 'user_icon7', 'user_icon8', 'user_icon9', 'user_icon10', + ), + ); + + // Execute overall actions + switch ($action) + { + case 'delete': + if ($style_id) + { + $this->remove($mode, $style_id); + return; + } + break; + + case 'export': + if ($style_id) + { + $this->export($mode, $style_id); + return; + } + break; + + case 'install': + $this->install($mode); + return; + break; + + case 'add': + $this->add($mode); + return; + break; + + case 'details': + if ($style_id) + { + $this->details($mode, $style_id); + return; + } + break; + + case 'edit': + if ($style_id) + { + switch ($mode) + { + case 'imageset': + return $this->edit_imageset($style_id); + case 'template': + return $this->edit_template($style_id); + case 'theme': + return $this->edit_theme($style_id); + } + } + break; + + case 'cache': + if ($style_id) + { + switch ($mode) + { + case 'template': + return $this->template_cache($style_id); + } + } + break; + } + + switch ($mode) + { + case 'style': + + switch ($action) + { + case 'activate': + case 'deactivate': + + if ($style_id == $config['default_style']) + { + trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'UPDATE ' . STYLES_TABLE . ' + SET style_active = ' . (($action == 'activate') ? 1 : 0) . ' + WHERE style_id = ' . $style_id; + $db->sql_query($sql); + + // Set style to default for any member using deactivated style + if ($action == 'deactivate') + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_style = ' . $config['default_style'] . " + WHERE user_style = $style_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET forum_style = 0 + WHERE forum_style = ' . $style_id; + $db->sql_query($sql); + } + break; + } + + $this->frontend('style', array('details'), array('export', 'delete')); + break; + + case 'template': + + switch ($action) + { + // Clear cache + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $style_id"; + $result = $db->sql_query($sql); + $template_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_row) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $this->clear_template_cache($template_row); + + trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + + break; + } + + $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete')); + break; + + case 'theme': + + switch ($action) + { + // Refresh theme data stored in the database + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_THEME_TABLE . " + WHERE theme_id = $style_id"; + $result = $db->sql_query($sql); + $theme_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$theme_row) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (!$theme_row['theme_storedb']) + { + trigger_error($user->lang['THEME_ERR_REFRESH_FS'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + if ($theme_row['theme_storedb'] && file_exists(PHPBB_ROOT_PATH . "styles/{$theme_row['theme_path']}/theme/stylesheet.css")) + { + // Save CSS contents + $sql_ary = array( + 'theme_mtime' => (int) filemtime(PHPBB_ROOT_PATH . "styles/{$theme_row['theme_path']}/theme/stylesheet.css"), + 'theme_data' => $this->db_theme_data($theme_row) + ); + + $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE theme_id = $style_id"; + $db->sql_query($sql); + + $cache->destroy('sql', STYLES_THEME_TABLE); + + add_log('admin', 'LOG_THEME_REFRESHED', $theme_row['theme_name']); + trigger_error($user->lang['THEME_REFRESHED'] . adm_back_link($this->u_action)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_THEME_REFRESH'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + break; + } + + $this->frontend('theme', array('edit', 'details'), array('refresh', 'export', 'delete')); + break; + + case 'imageset': + + switch ($action) + { + case 'refresh': + + $sql = 'SELECT * + FROM ' . STYLES_IMAGESET_TABLE . " + WHERE imageset_id = $style_id"; + $result = $db->sql_query($sql); + $imageset_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$imageset_row) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql_ary = array(); + + $imageset_definitions = array(); + foreach ($this->imageset_keys as $topic => $key_array) + { + $imageset_definitions = array_merge($imageset_definitions, $key_array); + } + + $cfg_data_imageset = parse_cfg_file(PHPBB_ROOT_PATH . "styles/{$imageset_row['imageset_path']}/imageset/imageset.cfg"); + + $db->sql_transaction('begin'); + + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $style_id; + $result = $db->sql_query($sql); + + foreach ($cfg_data_imageset as $image_name => $value) + { + if (strpos($value, '*') !== false) + { + if (substr($value, -1, 1) === '*') + { + list($image_filename, $image_height) = explode('*', $value); + $image_width = 0; + } + else + { + list($image_filename, $image_height, $image_width) = explode('*', $value); + } + } + else + { + $image_filename = $value; + $image_height = $image_width = 0; + } + + if (strpos($image_name, 'img_') === 0 && $image_filename) + { + $image_name = substr($image_name, 4); + if (in_array($image_name, $imageset_definitions)) + { + $sql_ary[] = array( + 'image_name' => (string) $image_name, + 'image_filename' => (string) $image_filename, + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $style_id, + 'image_lang' => '', + ); + } + } + } + + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (@file_exists(PHPBB_ROOT_PATH . "styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file(PHPBB_ROOT_PATH . "styles/{$imageset_row['imageset_path']}/imageset/{$row['lang_dir']}/imageset.cfg"); + foreach ($cfg_data_imageset_data as $image_name => $value) + { + if (strpos($value, '*') !== false) + { + if (substr($value, -1, 1) === '*') + { + list($image_filename, $image_height) = explode('*', $value); + $image_width = 0; + } + else + { + list($image_filename, $image_height, $image_width) = explode('*', $value); + } + } + else + { + $image_filename = $value; + $image_height = $image_width = 0; + } + + if (strpos($image_name, 'img_') === 0 && $image_filename) + { + $image_name = substr($image_name, 4); + if (in_array($image_name, $imageset_definitions)) + { + $sql_ary[] = array( + 'image_name' => (string) $image_name, + 'image_filename' => (string) $image_filename, + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $style_id, + 'image_lang' => (string) $row['lang_dir'], + ); + } + } + } + } + } + $db->sql_freeresult($result); + + $db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); + + $db->sql_transaction('commit'); + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_REFRESHED', $imageset_row['imageset_name']); + trigger_error($user->lang['IMAGESET_REFRESHED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_IMAGESET_REFRESH'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'id' => $style_id + ))); + } + break; + } + + $this->frontend('imageset', array('edit', 'details'), array('refresh', 'export', 'delete')); + break; + } + } + + /** + * Build Frontend with supplied options + */ + function frontend($mode, $options, $actions) + { + global $user, $template, $db, $config; + + $sql_from = ''; + $style_count = array(); + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + + $sql = 'SELECT user_style, COUNT(user_style) AS style_count + FROM ' . USERS_TABLE . ' + GROUP BY user_style'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $style_count[$row['user_style']] = $row['style_count']; + } + $db->sql_freeresult($result); + + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_prefix = strtoupper($mode); + + $this->page_title = 'ACP_' . $l_prefix . 'S'; + + $template->assign_vars(array( + 'S_FRONTEND' => true, + 'S_STYLE' => ($mode == 'style') ? true : false, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix], + 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix], + 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix], + 'L_CREATE' => $user->lang['CREATE_' . $l_prefix], + + 'U_ACTION' => $this->u_action, + ) + ); + + $sql = "SELECT * + FROM $sql_from"; + $result = $db->sql_query($sql); + + $installed = array(); + + $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>'; + while ($row = $db->sql_fetchrow($result)) + { + $installed[] = $row[$mode . '_name']; + $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; + + $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate'; + + $s_options = array(); + foreach ($options as $option) + { + $s_options[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; + } + + $s_actions = array(); + foreach ($actions as $option) + { + $s_actions[] = '<a href="' . $this->u_action . "&action=$option&id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>'; + } + + $template->assign_block_vars('installed', array( + 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false, + 'U_EDIT' => $this->u_action . '&action=' . (($mode == 'style') ? 'details' : 'edit') . '&id=' . $row[$mode . '_id'], + 'U_STYLE_ACT_DEACT' => $this->u_action . '&action=' . $stylevis . '&id=' . $row[$mode . '_id'], + 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)], + 'S_OPTIONS' => implode(' | ', $s_options), + 'S_ACTIONS' => implode(' | ', $s_actions), + 'U_PREVIEW' => ($mode == 'style') ? append_sid('index', "style=" . $row[$mode . '_id']) : '', + + 'NAME' => $row[$mode . '_name'], + 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0, + ) + ); + } + $db->sql_freeresult($result); + + // Grab uninstalled items + $new_ary = $cfg = array(); + + $dp = @opendir(PHPBB_ROOT_PATH . 'styles'); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + $subpath = ($mode != 'style') ? "$mode/" : ''; + if ($file[0] != '.' && file_exists(PHPBB_ROOT_PATH . "styles/$file/$subpath$mode.cfg")) + { + if ($cfg = file(PHPBB_ROOT_PATH . "styles/$file/$subpath$mode.cfg")) + { + $items = parse_cfg_file('', $cfg); + $name = (isset($items['name'])) ? trim($items['name']) : false; + + if ($name && !in_array($name, $installed)) + { + $new_ary[] = array( + 'path' => $file, + 'name' => $name, + 'copyright' => $items['copyright'], + ); + } + } + } + } + closedir($dp); + } + + unset($installed); + + if (sizeof($new_ary)) + { + foreach ($new_ary as $cfg) + { + $template->assign_block_vars('uninstalled', array( + 'NAME' => $cfg['name'], + 'COPYRIGHT' => $cfg['copyright'], + 'U_INSTALL' => $this->u_action . '&action=install&path=' . urlencode($cfg['path'])) + ); + } + } + unset($new_ary); + + $template->assign_vars(array( + 'S_BASIS_OPTIONS' => $basis_options) + ); + + } + + /** + * Provides a template editor which allows saving changes to template files on the filesystem or in the database. + * + * @param int $template_id specifies which template set is being edited + */ + function edit_template($template_id) + { + global $config, $db, $cache, $user, $template, $safe_mode; + + if (defined('PHPBB_DISABLE_ACP_EDITOR')) + { + trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action)); + } + + $this->page_title = 'EDIT_TEMPLATE'; + + $filelist = $filelist_cats = array(); + + $template_data = utf8_normalize_nfc(request_var('template_data', '', true)); + $template_data = htmlspecialchars_decode($template_data); + $template_file = utf8_normalize_nfc(request_var('template_file', '', true)); + $text_rows = max(5, min(999, request_var('text_rows', 20))); + $save_changes = request::is_set_post('save'); + + // make sure template_file path doesn't go upwards + $template_file = str_replace('..', '.', $template_file); + + // Retrieve some information about the template + $sql = 'SELECT template_path, template_name + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $template_id"; + $result = $db->sql_query($sql); + $template_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_info) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($save_changes && !check_form_key('acp_styles')) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING); + } + else if (!$save_changes) + { + add_form_key('acp_styles'); + } + + // save changes to the template if the user submitted any + if ($save_changes && $template_file) + { + // Get the filesystem location of the current file + $file = PHPBB_ROOT_PATH . "styles/{$template_info['template_path']}/template/$template_file"; + $additional = ''; + + // If the template is stored on the filesystem try to write the file else store it in the database + //if (!$safe_mode && !$template_info['template_storedb'] && file_exists($file) && @is_writable($file)) + if (!($fp = @fopen($file, 'wb'))) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + fwrite($fp, $template_data); + fclose($fp); + + // destroy the cached version of the template (filename without extension) + $this->clear_template_cache($template_info, array(substr($template_file, 0, -5))); + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file); + trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . $additional . adm_back_link($this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows&template_file=$template_file")); + } + + // Generate a category array containing template filenames + $template_path = PHPBB_ROOT_PATH . "styles/{$template_info['template_path']}/template"; + + $filelist = filelist($template_path, '', 'html'); + $filelist[''] = array_diff($filelist[''], array('bbcode.html')); + + if ($template_file) + { + if (!file_exists($template_path . "/$template_file") || !($template_data = file_get_contents($template_path . "/$template_file"))) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // Now create the categories + $filelist_cats[''] = array(); + foreach ($filelist as $pathfile => $file_ary) + { + // Use the directory name as category name + if (!empty($pathfile)) + { + $filelist_cats[$pathfile] = array(); + foreach ($file_ary as $file) + { + $filelist_cats[$pathfile][$pathfile . $file] = $file; + } + } + // or if it's in the main category use the word before the first underscore to group files + else + { + $cats = array(); + foreach ($file_ary as $file) + { + $cats[] = substr($file, 0, strpos($file, '_')); + $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; + } + + $cats = array_values(array_unique($cats)); + + // we don't need any single element categories so put them into the misc '' category + for ($i = 0, $n = sizeof($cats); $i < $n; $i++) + { + if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') + { + $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); + unset($filelist_cats[$cats[$i]]); + } + } + unset($cats); + } + } + unset($filelist); + + // Generate list of categorised template files + $tpl_options = ''; + ksort($filelist_cats); + foreach ($filelist_cats as $category => $tpl_ary) + { + ksort($tpl_ary); + + if (!empty($category)) + { + $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; + } + + foreach ($tpl_ary as $filename => $file) + { + $selected = ($template_file == $filename) ? ' selected="selected"' : ''; + $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; + } + } + + $template->assign_vars(array( + 'S_EDIT_TEMPLATE' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)), + 'S_TEMPLATES' => $tpl_options, + + 'U_ACTION' => $this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows", + 'U_BACK' => $this->u_action, + + 'L_EDIT' => $user->lang['EDIT_TEMPLATE'], + 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'], + 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'], + 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'], + 'L_FILE' => $user->lang['TEMPLATE_FILE'], + 'L_SELECT' => $user->lang['SELECT_TEMPLATE'], + 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'], + 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'], + + 'SELECTED_TEMPLATE' => $template_info['template_name'], + 'TEMPLATE_FILE' => $template_file, + 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data), + 'TEXT_ROWS' => $text_rows) + ); + } + + /** + * Allows the admin to view cached versions of template files and clear single template cache files + * + * @param int $template_id specifies which template's cache is shown + */ + function template_cache($template_id) + { + global $config, $db, $cache, $user, $template; + + $source = str_replace('/', '.', request_var('source', '')); + $file_ary = array_diff(request_var('delete', array('')), array('')); + $submit = request::is_set_post('submit'); + + $sql = 'SELECT * + FROM ' . STYLES_TEMPLATE_TABLE . " + WHERE template_id = $template_id"; + $result = $db->sql_query($sql); + $template_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$template_row) + { + trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // User wants to delete one or more files ... + if ($submit && $file_ary) + { + $this->clear_template_cache($template_row, $file_ary); + trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&action=cache&id=$template_id")); + } + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); + + // Someone wants to see the cached source ... so we'll highlight it, + // add line numbers and indent it appropriately. This could be nasty + // on larger source files ... + if ($source && file_exists(PHPBB_ROOT_PATH . "cache/{$cache_prefix}_$source.html." . PHP_EXT)) + { + adm_page_header($user->lang['TEMPLATE_CACHE']); + + $template->set_filenames(array( + 'body' => 'viewsource.html') + ); + + $template->assign_vars(array( + 'FILENAME' => str_replace('.', '/', $source) . '.html') + ); + + $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents(PHPBB_ROOT_PATH . "cache/{$cache_prefix}_$source.html." . PHP_EXT)); + + $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string'); + foreach ($conf as $ini_var) + { + @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var)); + } + + $marker = 'MARKER' . time(); + $code = highlight_string(str_replace("\n", $marker, $code), true); + $code = str_replace($marker, "\n", $code); + $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':'); + $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '[', ']', '.', ':'); + + $code = str_replace($str_from, $str_to, $code); + $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code); + $code = substr($code, strlen('<span class="syntaxhtml">')); + $code = substr($code, 0, -1 * strlen('</ span>')); + $code = explode("\n", $code); + + foreach ($code as $key => $line) + { + $template->assign_block_vars('source', array( + 'LINENUM' => $key + 1, + 'LINE' => preg_replace('#([^ ;]) ([^ &])#', '$1 $2', $line)) + ); + unset($code[$key]); + } + + adm_page_footer(); + } + + // Get a list of cached template files and then retrieve additional information about them + $file_ary = $this->template_cache_filelist($template_row['template_path']); + + foreach ($file_ary as $file) + { + $file = str_replace('/', '.', $file); + + // perform some dirty guessing to get the path right. + // We assume that three dots in a row were '../' + $tpl_file = str_replace('.', '/', $file); + $tpl_file = str_replace('///', '../', $tpl_file); + + $filename = "{$cache_prefix}_$file.html." . PHP_EXT; + + if (!file_exists(PHPBB_ROOT_PATH . "cache/$filename")) + { + continue; + } + + $template->assign_block_vars('file', array( + 'U_VIEWSOURCE' => $this->u_action . "&action=cache&id=$template_id&source=$file", + + 'CACHED' => $user->format_date(filemtime(PHPBB_ROOT_PATH . "cache/$filename")), + 'FILENAME' => $file, + 'FILESIZE' => sprintf('%.1f ' . $user->lang['KIB'], filesize(PHPBB_ROOT_PATH . "cache/$filename") / 1024), + 'MODIFIED' => $user->format_date(filemtime(PHPBB_ROOT_PATH . "styles/{$template_row['template_path']}/template/$tpl_file.html"))) + ); + } + + $template->assign_vars(array( + 'S_CACHE' => true, + 'S_TEMPLATE' => true, + + 'U_ACTION' => $this->u_action . "&action=cache&id=$template_id", + 'U_BACK' => $this->u_action) + ); + } + + /** + * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users + * + * @param int $theme_id specifies which theme is being edited + */ + function edit_theme($theme_id) + { + global $config, $db, $cache, $user, $template, $safe_mode; + + $this->page_title = 'EDIT_THEME'; + + $filelist = $filelist_cats = array(); + + $theme_data = utf8_normalize_nfc(request_var('template_data', '', true)); + $theme_data = htmlspecialchars_decode($theme_data); + $theme_file = utf8_normalize_nfc(request_var('template_file', '', true)); + $text_rows = max(5, min(999, request_var('text_rows', 20))); + $save_changes = request::is_set_post('save'); + + // make sure theme_file path doesn't go upwards + $theme_file = str_replace('..', '.', $theme_file); + + // Retrieve some information about the theme + $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data + FROM ' . STYLES_THEME_TABLE . " + WHERE theme_id = $theme_id"; + $result = $db->sql_query($sql); + + if (!($theme_info = $db->sql_fetchrow($result))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + $db->sql_freeresult($result); + + $theme_info['theme_id'] = $theme_id; + self::generate_stylesheets($theme_info); + + // save changes to the theme if the user submitted any + if ($save_changes) + { + // Get the filesystem location of the current file + $file = PHPBB_ROOT_PATH . "styles/{$theme_info['theme_path']}/theme/$theme_file"; + $additional = ''; + $message = $user->lang['THEME_UPDATED']; + + // If the theme is stored on the filesystem try to write the file else store it in the database + if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file)) + { + if (!($fp = @fopen($file, 'wb'))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + fwrite($fp, $theme_data); + fclose($fp); + } + else + { + // Write stylesheet to db + $sql_ary = array( + 'theme_mtime' => time(), + 'theme_storedb' => 1, + 'theme_data' => $this->db_theme_data($theme_info, $theme_data), + ); + $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE theme_id = ' . $theme_id; + $db->sql_query($sql); + + $cache->destroy('sql', STYLES_THEME_TABLE); + + // notify the user if the theme was not stored in the db before his modification + if (!$theme_info['theme_storedb']) + { + add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']); + $message .= '<br />' . $user->lang['EDIT_THEME_STORED_DB']; + } + } + $cache->destroy('sql', STYLES_THEME_TABLE); + add_log('admin', (!$theme_info['theme_storedb']) ? 'LOG_THEME_EDIT_FILE' : 'LOG_THEME_EDIT', $theme_info['theme_name'], (!$theme_info['theme_storedb']) ? $theme_file : ''); + + trigger_error($message . adm_back_link($this->u_action . "&action=edit&id=$theme_id&template_file=$theme_file&text_rows=$text_rows")); + } + + // Generate a category array containing theme filenames + if (!$theme_info['theme_storedb']) + { + $theme_path = PHPBB_ROOT_PATH ."styles/{$theme_info['theme_path']}/theme"; + + $filelist = filelist($theme_path, '', 'css'); + + if ($theme_file) + { + if (!file_exists($theme_path . "/$theme_file") || !($theme_data = file_get_contents($theme_path . "/$theme_file"))) + { + trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + } + else + { + $theme_data = &$theme_info['theme_data']; + } + + // Now create the categories + $filelist_cats[''] = array(); + foreach ($filelist as $pathfile => $file_ary) + { + // Use the directory name as category name + if (!empty($pathfile)) + { + $filelist_cats[$pathfile] = array(); + foreach ($file_ary as $file) + { + $filelist_cats[$pathfile][$pathfile . $file] = $file; + } + } + // or if it's in the main category use the word before the first underscore to group files + else + { + $cats = array(); + foreach ($file_ary as $file) + { + $cats[] = substr($file, 0, strpos($file, '_')); + $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file; + } + + $cats = array_values(array_unique($cats)); + + // we don't need any single element categories so put them into the misc '' category + for ($i = 0, $n = sizeof($cats); $i < $n; $i++) + { + if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') + { + $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); + unset($filelist_cats[$cats[$i]]); + } + } + unset($cats); + } + } + unset($filelist); + + // Generate list of categorised theme files + $tpl_options = ''; + ksort($filelist_cats); + foreach ($filelist_cats as $category => $tpl_ary) + { + ksort($tpl_ary); + + if (!empty($category)) + { + $tpl_options .= '<option class="sep" value="">' . $category . '</option>'; + } + + foreach ($tpl_ary as $filename => $file) + { + $selected = ($theme_file == $filename) ? ' selected="selected"' : ''; + $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>'; + } + } + + $template->assign_vars(array( + 'S_EDIT_THEME' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)), + 'S_THEME_IN_DB' => $theme_info['theme_storedb'], + 'S_TEMPLATES' => $tpl_options, + + 'U_ACTION' => $this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows", + 'U_BACK' => $this->u_action, + + 'L_EDIT' => $user->lang['EDIT_THEME'], + 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'], + 'L_EDITOR' => $user->lang['THEME_EDITOR'], + 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'], + 'L_FILE' => $user->lang['THEME_FILE'], + 'L_SELECT' => $user->lang['SELECT_THEME'], + 'L_SELECTED' => $user->lang['SELECTED_THEME'], + 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'], + + 'SELECTED_TEMPLATE' => $theme_info['theme_name'], + 'TEMPLATE_FILE' => $theme_file, + 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data), + 'TEXT_ROWS' => $text_rows) + ); + } + + + /** + * Edit imagesets + * + * @param int $imageset_id specifies which imageset is being edited + */ + function edit_imageset($imageset_id) + { + global $db, $user, $cache, $template; + + $this->page_title = 'EDIT_IMAGESET'; + + $update = request::is_set_post('update'); + + $imgname = request_var('imgname', ''); + $imgpath = request_var('imgpath', ''); + $imgsize = request_var('imgsize', false); + $imgwidth = request_var('imgwidth', 0); + $imgheight = request_var('imgheight', 0); + + $imgname = preg_replace('#[^a-z0-9\-+_]#i', '', $imgname); + $imgpath = str_replace('..', '.', $imgpath); + + if ($imageset_id) + { + $sql = 'SELECT imageset_path, imageset_name + FROM ' . STYLES_IMAGESET_TABLE . " + WHERE imageset_id = $imageset_id"; + $result = $db->sql_query($sql); + $imageset_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $imageset_path = $imageset_row['imageset_path']; + $imageset_name = $imageset_row['imageset_name']; + + $sql_extra = ''; + if (strpos($imgname, '-') !== false) + { + list($imgname, $imgnamelang) = explode('-', $imgname); + $sql_extra = " AND image_lang IN ('" . $db->sql_escape($imgnamelang) . "', '')"; + } + + $sql = 'SELECT image_filename, image_width, image_height, image_lang, image_id + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $imageset_id + AND image_name = '" . $db->sql_escape($imgname) . "'$sql_extra"; + $result = $db->sql_query($sql); + $imageset_data_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $image_filename = $imageset_data_row['image_filename']; + $image_width = $imageset_data_row['image_width']; + $image_height = $imageset_data_row['image_height']; + $image_lang = $imageset_data_row['image_lang']; + $image_id = $imageset_data_row['image_id']; + + if (!$imageset_row) + { + trigger_error($user->lang['NO_IMAGESET'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Check to see whether the selected image exists in the table + $valid_name = ($update) ? false : true; + + foreach ($this->imageset_keys as $category => $img_ary) + { + if (in_array($imgname, $img_ary)) + { + $valid_name = true; + break; + } + } + + if ($update && request::is_set_post('imgpath')) + { + if ($valid_name) + { + // If imgwidth and imgheight are non-zero grab the actual size + // from the image itself ... we ignore width settings for the poll center image + $imgwidth = request_var('imgwidth', 0); + $imgheight = request_var('imgheight', 0); + $imglang = ''; + + if ($imgpath && !file_exists(PHPBB_ROOT_PATH . "styles/$imageset_path/imageset/$imgpath")) + { + trigger_error($user->lang['NO_IMAGE_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if ($imgsize && $imgpath) + { + if (!$imgwidth || !$imgheight) + { + list($imgwidth_file, $imgheight_file) = getimagesize(PHPBB_ROOT_PATH . "styles/$imageset_path/imageset/$imgpath"); + $imgwidth = ($imgwidth) ? $imgwidth : $imgwidth_file; + $imgheight = ($imgheight) ? $imgheight : $imgheight_file; + } + $imgwidth = ($imgname != 'poll_center') ? (int) $imgwidth : 0; + $imgheight = (int) $imgheight; + } + + + if (strpos($imgpath, '/') !== false) + { + list($imglang, $imgfilename) = explode('/', $imgpath); + } + else + { + $imgfilename = $imgpath; + } + + $sql_ary = array( + 'image_filename' => (string) $imgfilename, + 'image_width' => (int) $imgwidth, + 'image_height' => (int) $imgheight, + 'image_lang' => (string) $imglang, + ); + + // already exists + if ($imageset_data_row) + { + $sql = 'UPDATE ' . STYLES_IMAGESET_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE image_id = $image_id"; + $db->sql_query($sql); + } + // does not exist + else if (!$imageset_data_row) + { + $sql_ary['image_name'] = $imgname; + $sql_ary['imageset_id'] = (int) $imageset_id; + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + + $cache->destroy('sql', STYLES_IMAGESET_DATA_TABLE); + + add_log('admin', 'LOG_IMAGESET_EDIT', $imageset_name); + + $template->assign_var('SUCCESS', true); + + $image_filename = $imgfilename; + $image_width = $imgwidth; + $image_height = $imgheight; + $image_lang = $imglang; + } + } + } + + $imglang = ''; + $imagesetlist = array('nolang' => array(), 'lang' => array()); + $langs = array(); + + $dir = PHPBB_ROOT_PATH . "styles/$imageset_path/imageset"; + $dp = @opendir($dir); + + if ($dp) + { + while (($file = readdir($dp)) !== false) + { + if ($file[0] != '.' && strtoupper($file) != 'CVS' && !is_file($dir . '/' . $file) && !is_link($dir . '/' . $file)) + { + $langs[] = $file; + } + else if (preg_match('#\.(?:gif|jpg|png)$#', $file)) + { + $imagesetlist['nolang'][] = $file; + } + } + + if ($sql_extra) + { + $dp2 = @opendir("$dir/$imgnamelang"); + + if ($dp2) + { + while (($file2 = readdir($dp2)) !== false) + { + if (preg_match('#\.(?:gif|jpg|png)$#', $file2)) + { + $imagesetlist['lang'][] = "$imgnamelang/$file2"; + } + } + closedir($dp2); + } + } + closedir($dp); + } + + // Generate list of image options + $img_options = ''; + foreach ($this->imageset_keys as $category => $img_ary) + { + $template->assign_block_vars('category', array( + 'NAME' => $user->lang['IMG_CAT_' . strtoupper($category)] + )); + + foreach ($img_ary as $img) + { + if ($category == 'buttons') + { + foreach ($langs as $language) + { + $template->assign_block_vars('category.images', array( + 'SELECTED' => ($img == $imgname && $language == $imgnamelang), + 'VALUE' => $img . '-' . $language, + 'TEXT' => $user->lang['IMG_' . strtoupper($img)] . ' [ ' . $language . ' ]' + )); + } + } + else + { + $template->assign_block_vars('category.images', array( + 'SELECTED' => ($img == $imgname), + 'VALUE' => $img, + 'TEXT' => (($category == 'custom') ? $img : $user->lang['IMG_' . strtoupper($img)]) + )); + } + } + } + + // Make sure the list of possible images is sorted alphabetically + sort($imagesetlist['lang']); + sort($imagesetlist['nolang']); + + $image_found = false; + $img_val = ''; + foreach ($imagesetlist as $type => $img_ary) + { + if ($type !== 'lang' || $sql_extra) + { + $template->assign_block_vars('imagesetlist', array( + 'TYPE' => ($type == 'lang') + )); + } + + foreach ($img_ary as $img) + { + $imgtext = preg_replace('/^([^\/]+\/)/', '', $img); + $selected = (!empty($imgname) && strpos($image_filename, $imgtext) !== false); + if ($selected) + { + $image_found = true; + $img_val = htmlspecialchars($img); + } + $template->assign_block_vars('imagesetlist.images', array( + 'SELECTED' => $selected, + 'TEXT' => $imgtext, + 'VALUE' => htmlspecialchars($img) + )); + } + } + + $imgsize_bool = (!empty($imgname) && $image_width && $image_height) ? true : false; + $image_request = '../styles/' . $imageset_path . '/imageset/' . ($image_lang ? $imgnamelang . '/' : '') . $image_filename; + + $template->assign_vars(array( + 'S_EDIT_IMAGESET' => true, + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'IMAGE_OPTIONS' => $img_options, + 'IMAGE_SIZE' => $image_width, + 'IMAGE_HEIGHT' => $image_height, + 'IMAGE_REQUEST' => (empty($image_filename)) ? 'images/no_image.png' : $image_request, + 'U_ACTION' => $this->u_action . "&action=edit&id=$imageset_id", + 'U_BACK' => $this->u_action, + 'NAME' => $imageset_name, + 'A_NAME' => addslashes($imageset_name), + 'ERROR' => !$valid_name, + 'IMG_SRC' => ($image_found) ? '../styles/' . $imageset_path . '/imageset/' . $img_val : 'images/no_image.png', + 'IMAGE_SELECT' => $image_found + )); + } + + /** + * Remove style/template/theme/imageset + */ + function remove($mode, $style_id) + { + global $db, $template, $user, $cache, $config; + + $new_id = request_var('new_id', 0); + $update = request::is_set_post('update'); + $sql_where = ''; + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + $sql_select = 'style_name'; + $sql_where = 'AND style_active = 1'; + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + $sql_select = 'template_name, template_path'; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + $sql_select = 'theme_name, theme_path, theme_storedb'; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + $sql_select = 'imageset_name, imageset_path'; + break; + } + + $l_prefix = strtoupper($mode); + + $sql = "SELECT $sql_select + FROM $sql_from + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = "SELECT {$mode}_id, {$mode}_name + FROM $sql_from + WHERE {$mode}_id <> $style_id + $sql_where + ORDER BY {$mode}_name ASC"; + $result = $db->sql_query($sql); + + $s_options = ''; + + if ($row = $db->sql_fetchrow($result)) + { + do + { + $s_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>'; + } + while ($row = $db->sql_fetchrow($result)); + } + else + { + trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + $db->sql_freeresult($result); + + if ($update) + { + $sql = "DELETE FROM $sql_from + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + + if ($mode == 'style') + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $new_id + WHERE user_style = $style_id"; + $db->sql_query($sql); + + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_style = $new_id + WHERE forum_style = $style_id"; + $db->sql_query($sql); + + if ($style_id == $config['default_style']) + { + set_config('default_style', $new_id); + } + } + else + { + if ($mode == 'imageset') + { + $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id"; + $db->sql_query($sql); + } + $sql = 'UPDATE ' . STYLES_TABLE . " + SET {$mode}_id = $new_id + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + } + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']); + $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED'; + trigger_error($user->lang[$message] . adm_back_link($this->u_action)); + } + + $this->page_title = 'DELETE_' . $l_prefix; + + $template->assign_vars(array( + 'S_DELETE' => true, + 'S_REPLACE_OPTIONS' => $s_options, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + 'L_REPLACE' => $user->lang['REPLACE_' . $l_prefix], + 'L_REPLACE_EXPLAIN' => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'], + + 'U_ACTION' => $this->u_action . "&action=delete&id=$style_id", + 'U_BACK' => $this->u_action, + + 'NAME' => $style_row[$mode . '_name'], + ) + ); + } + + /** + * Export style or style elements + */ + function export($mode, $style_id) + { + global $db, $template, $user, $cache, $config; + + $update = request::is_set_post('update'); + + $inc_template = request_var('inc_template', 0); + $inc_theme = request_var('inc_theme', 0); + $inc_imageset = request_var('inc_imageset', 0); + $store = request_var('store', 0); + $format = request_var('format', ''); + + $error = array(); + $methods = array('tar'); + + $available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib'); + foreach ($available_methods as $type => $module) + { + if (!@extension_loaded($module)) + { + continue; + } + + $methods[] = $type; + } + + if (!in_array($format, $methods)) + { + $format = 'tar'; + } + + switch ($mode) + { + case 'style': + if ($update && ($inc_template + $inc_theme + $inc_imageset) < 1) + { + $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS']; + } + + $name = 'style_name'; + + $sql_select = 's.style_id, s.style_name, s.style_copyright'; + $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name'; + $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name'; + $sql_select .= ($inc_imageset) ? ', i.*' : ', i.imageset_name'; + $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . ' i'; + $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id AND i.imageset_id = s.imageset_id"; + + $l_prefix = 'STYLE'; + break; + + case 'template': + $name = 'template_name'; + + $sql_select = '*'; + $sql_from = STYLES_TEMPLATE_TABLE; + $sql_where = "template_id = $style_id"; + + $l_prefix = 'TEMPLATE'; + break; + + case 'theme': + $name = 'theme_name'; + + $sql_select = '*'; + $sql_from = STYLES_THEME_TABLE; + $sql_where = "theme_id = $style_id"; + + $l_prefix = 'THEME'; + break; + + case 'imageset': + $name = 'imageset_name'; + + $sql_select = '*'; + $sql_from = STYLES_IMAGESET_TABLE; + $sql_where = "imageset_id = $style_id"; + + $l_prefix = 'IMAGESET'; + break; + } + + if ($update && !sizeof($error)) + { + $sql = "SELECT $sql_select + FROM $sql_from + WHERE $sql_where"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright', 'theme_storedb', 'theme_mtime', 'theme_data', 'imageset_id', 'imageset_name', 'imageset_path', 'imageset_copyright'); + + foreach ($var_ary as $var) + { + if (!isset($style_row[$var])) + { + $style_row[$var] = ''; + } + } + + $files = $data = array(); + + if ($mode == 'style') + { + $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg); + + $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : ''; + $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : ''; + $style_cfg .= (!$inc_imageset) ? "\nrequired_imageset = {$style_row['imageset_name']}" : ''; + + $data[] = array( + 'src' => $style_cfg, + 'prefix' => 'style.cfg' + ); + + unset($style_cfg); + } + + // Export template core code + if ($mode == 'template' || $inc_template) + { + $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version']), $this->template_cfg); + + $data[] = array( + 'src' => $template_cfg, + 'prefix' => 'template/template.cfg' + ); + + // This is potentially nasty memory-wise ... + $files[] = array( + 'src' => "styles/{$style_row['template_path']}/template/", + 'prefix-' => "styles/{$style_row['template_path']}/", + 'prefix+' => false, + 'exclude' => 'template.cfg' + ); + unset($template_cfg); + } + + // Export theme core code + if ($mode == 'theme' || $inc_theme) + { + $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg); + + // Read old cfg file + $items = cache::obtain_cfg_item($style_row, 'theme'); + + if (!isset($items['parse_css_file'])) + { + $items['parse_css_file'] = 'off'; + } + + $theme_cfg = str_replace(array('{PARSE_CSS_FILE}'), array($items['parse_css_file']), $theme_cfg); + + $files[] = array( + 'src' => "styles/{$style_row['theme_path']}/theme/", + 'prefix-' => "styles/{$style_row['theme_path']}/", + 'prefix+' => false, + 'exclude' => ($style_row['theme_storedb']) ? 'stylesheet.css,theme.cfg' : 'theme.cfg' + ); + + $data[] = array( + 'src' => $theme_cfg, + 'prefix' => 'theme/theme.cfg' + ); + + if ($style_row['theme_storedb']) + { + $data[] = array( + 'src' => $style_row['theme_data'], + 'prefix' => 'theme/stylesheet.css' + ); + } + + unset($items, $theme_cfg); + } + + // Export imageset core code + if ($mode == 'imageset' || $inc_imageset) + { + $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); + + $imageset_main = array(); + + $sql = 'SELECT image_filename, image_name, image_height, image_width + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id + AND image_lang = ''"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $imageset_main[$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); + } + $db->sql_freeresult($result); + + foreach ($this->imageset_keys as $topic => $key_array) + { + foreach ($key_array as $key) + { + if (isset($imageset_main[$key])) + { + $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_main[$key]); + } + } + } + + $files[] = array( + 'src' => "styles/{$style_row['imageset_path']}/imageset/", + 'prefix-' => "styles/{$style_row['imageset_path']}/", + 'prefix+' => false, + 'exclude' => 'imageset.cfg' + ); + + $data[] = array( + 'src' => trim($imageset_cfg), + 'prefix' => 'imageset/imageset.cfg' + ); + + end($data); + + $imageset_root = PHPBB_ROOT_PATH . "styles/{$style_row['imageset_path']}/imageset/"; + + if ($dh = @opendir($imageset_root)) + { + while (($fname = readdir($dh)) !== false) + { + if ($fname[0] != '.' && $fname != 'CVS' && is_dir("$imageset_root$fname")) + { + $files[key($files)]['exclude'] .= ',' . $fname . '/imageset.cfg'; + } + } + closedir($dh); + } + + $imageset_lang = array(); + + $sql = 'SELECT image_filename, image_name, image_height, image_width, image_lang + FROM ' . STYLES_IMAGESET_DATA_TABLE . " + WHERE imageset_id = $style_id + AND image_lang <> ''"; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $imageset_lang[$row['image_lang']][$row['image_name']] = $row['image_filename'] . ($row['image_height'] ? '*' . $row['image_height']: '') . ($row['image_width'] ? '*' . $row['image_width']: ''); + } + $db->sql_freeresult($result); + + foreach ($imageset_lang as $lang => $imageset_localized) + { + $imageset_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['imageset_name'], $style_row['imageset_copyright'], $config['version']), $this->imageset_cfg); + + foreach ($this->imageset_keys as $topic => $key_array) + { + foreach ($key_array as $key) + { + if (isset($imageset_localized[$key])) + { + $imageset_cfg .= "\nimg_" . $key . ' = ' . str_replace("styles/{$style_row['imageset_path']}/imageset/", '{PATH}', $imageset_localized[$key]); + } + } + } + + $data[] = array( + 'src' => trim($imageset_cfg), + 'prefix' => 'imageset/' . $lang . '/imageset.cfg' + ); + } + + unset($imageset_cfg); + } + + switch ($format) + { + case 'tar': + $ext = '.tar'; + $mimetype = 'x-tar'; + $compress = 'compress_tar'; + break; + + case 'zip': + $ext = '.zip'; + $mimetype = 'zip'; + break; + + case 'tar.gz': + $ext = '.tar.gz'; + $mimetype = 'x-gzip'; + break; + + case 'tar.bz2': + $ext = '.tar.bz2'; + $mimetype = 'x-bzip2'; + break; + + default: + $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE']; + } + + if (!sizeof($error)) + { + include(PHPBB_ROOT_PATH . 'includes/functions_compress.' . PHP_EXT); + + if ($mode == 'style') + { + $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']); + } + else + { + $path = $style_row[$mode . '_path']; + } + + if ($format == 'zip') + { + $compress = new compress_zip('w', PHPBB_ROOT_PATH . "store/$path$ext"); + } + else + { + $compress = new compress_tar('w', PHPBB_ROOT_PATH . "store/$path$ext", $ext); + } + + if (sizeof($files)) + { + foreach ($files as $file_ary) + { + $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']); + } + } + + if (sizeof($data)) + { + foreach ($data as $data_ary) + { + $compress->add_data($data_ary['src'], $data_ary['prefix']); + } + } + + $compress->close(); + + add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']); + + if (!$store) + { + $compress->download($path); + @unlink(PHPBB_ROOT_PATH . "store/$path$ext"); + exit; + } + + trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action)); + } + } + + $sql = "SELECT {$mode}_id, {$mode}_name + FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . " + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $this->page_title = $l_prefix . '_EXPORT'; + + $format_buttons = ''; + foreach ($methods as $method) + { + $format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>'; + } + + $template->assign_vars(array( + 'S_EXPORT' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_prefix . '_NAME'], + + 'U_ACTION' => $this->u_action . '&action=export&id=' . $style_id, + 'U_BACK' => $this->u_action, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'FORMAT_BUTTONS' => $format_buttons) + ); + } + + /** + * Display details + */ + function details($mode, $style_id) + { + global $template, $db, $config, $user, $safe_mode, $cache; + + $update = request::is_set_post('update'); + $l_type = strtoupper($mode); + + $error = array(); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + + switch ($mode) + { + case 'style': + $sql_from = STYLES_TABLE; + break; + + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT * + FROM $sql_from + WHERE {$mode}_id = $style_id"; + $result = $db->sql_query($sql); + $style_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$style_row) + { + trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0; + + if ($update) + { + $name = utf8_normalize_nfc(request_var('name', '', true)); + $copyright = utf8_normalize_nfc(request_var('copyright', '', true)); + + $template_id = request_var('template_id', 0); + $theme_id = request_var('theme_id', 0); + $imageset_id = request_var('imageset_id', 0); + + $style_active = request_var('style_active', 0); + $style_default = request_var('style_default', 0); + + $sql = "SELECT {$mode}_id + FROM $sql_from + WHERE {$mode}_id <> $style_id + AND {$mode}_name = '" . $db->sql_escape(strtolower($name)) . "'"; + $result = $db->sql_query($sql); + $conflict = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($mode == 'style' && (!$template_id || !$theme_id || !$imageset_id)) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + + if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id) + { + $error[] = $user->lang['DEACTIVATE_DEFAULT']; + } + + if (!$name || $conflict) + { + $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; + } + + if (!sizeof($error)) + { + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; + } + } + } + + if ($update && sizeof($error)) + { + $style_row = array_merge($style_row, array( + 'template_id' => $template_id, + 'theme_id' => $theme_id, + 'imageset_id' => $imageset_id, + 'style_active' => $style_active, + $mode . '_name' => $name, + $mode . '_copyright' => $copyright) + ); + } + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + $sql_ary = array( + $mode . '_name' => $name, + $mode . '_copyright' => $copyright + ); + + switch ($mode) + { + case 'style': + + $sql_ary += array( + 'template_id' => (int) $template_id, + 'theme_id' => (int) $theme_id, + 'imageset_id' => (int) $imageset_id, + 'style_active' => (int) $style_active, + ); + break; + + case 'imageset': + break; + + case 'theme': + break; + + case 'template': + break; + } + + if (sizeof($sql_ary)) + { + $sql = "UPDATE $sql_from + SET " . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE {$mode}_id = $style_id"; + $db->sql_query($sql); + + // Making this the default style? + if ($mode == 'style' && $style_default) + { + set_config('default_style', $style_id); + } + } + + $cache->destroy('sql', STYLES_TABLE); + + add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name); + if (sizeof($error)) + { + trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING); + } + else + { + trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action)); + } + } + + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + $sql = "SELECT {$element}_id, {$element}_name + FROM $table + ORDER BY {$element}_id ASC"; + $result = $db->sql_query($sql); + + ${$element . '_options'} = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; + ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + } + $db->sql_freeresult($result); + } + } + + $this->page_title = 'EDIT_DETAILS_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_THEME' => ($mode == 'theme') ? true : false, + 'S_IMAGESET' => ($mode == 'imageset') ? true : false, + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + + 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', + 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', + 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', + + 'U_ACTION' => $this->u_action . '&action=details&id=' . $style_id, + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright'], + ) + ); + } + + /** + * Load css file contents + */ + function load_css_file($path, $filename) + { + $file = PHPBB_ROOT_PATH . "styles/$path/theme/$filename"; + + if (file_exists($file) && ($content = file_get_contents($file))) + { + $content = trim($content); + } + else + { + $content = ''; + } + + return $content; + } + + /** + * Returns a string containing the value that should be used for the theme_data column in the theme database table. + * Includes contents of files loaded via @import + * + * @param array $theme_row is an associative array containing the theme's current database entry + * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file + * @param string $root_path should only be used in case you want to use a different root path than PHPBB_ROOT_PATH . "styles/{$theme_row['theme_path']}" + * + * @return string Stylesheet data for theme_data column in the theme table + */ + function db_theme_data($theme_row, $stylesheet = false, $root_path = '') + { + if (!$root_path) + { + $root_path = PHPBB_ROOT_PATH . 'styles/' . $theme_row['theme_path']; + } + + if (!$stylesheet) + { + $stylesheet = ''; + if (file_exists($root_path . '/theme/stylesheet.css')) + { + $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css'); + } + } + + // Match CSS imports + $matches = array(); + preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); + + if (sizeof($matches)) + { + foreach ($matches[0] as $idx => $match) + { + $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[1][$idx]), $stylesheet); + } + } + + // adjust paths + return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet); + } + + /** + * Returns an array containing all template filenames for one template that are currently cached. + * + * @param string $template_path contains the name of the template's folder in /styles/ + * + * @return array of filenames that exist in /styles/$template_path/template/ (without extension!) + */ + function template_cache_filelist($template_path) + { + global $user; + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path); + + if (!($dp = @opendir(PHPBB_ROOT_PATH . 'cache'))) + { + trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $file_ary = array(); + while ($file = readdir($dp)) + { + if ($file[0] == '.') + { + continue; + } + + if (is_file(PHPBB_ROOT_PATH . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0)) + { + $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . PHP_EXT . '$#i', '\1', $file)); + } + } + closedir($dp); + + return $file_ary; + } + + /** + * Destroys cached versions of template files + * + * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table + * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache. + * The file names should be the original template file names and not the cache file names. + */ + function clear_template_cache($template_row, $file_ary = false) + { + global $user; + + $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']); + + if (!$file_ary || !is_array($file_ary)) + { + $file_ary = $this->template_cache_filelist($template_row['template_path']); + $log_file_list = $user->lang['ALL_FILES']; + } + else + { + $log_file_list = implode(', ', $file_ary); + } + + foreach ($file_ary as $file) + { + $file = str_replace('/', '.', $file); + + $file = PHPBB_ROOT_PATH . "cache/{$cache_prefix}_$file.html." . PHP_EXT; + if (file_exists($file) && is_file($file)) + { + @unlink($file); + } + } + unset($file_ary); + + add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list); + } + + /** + * Install Style/Template/Theme/Imageset + */ + function install($mode) + { + global $config, $db, $cache, $user, $template; + + $l_type = strtoupper($mode); + + $error = $installcfg = $style_row = array(); + $root_path = $cfg_file = ''; + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + + $install_path = request_var('path', ''); + $update = request::is_set_post('update'); + + // Installing, obtain cfg file contents + if ($install_path) + { + $root_path = PHPBB_ROOT_PATH . 'styles/' . $install_path . '/'; + $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg"; + + if (!file_exists($cfg_file)) + { + $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type]; + } + else + { + $installcfg = parse_cfg_file($cfg_file); + } + } + + // Installing + if (sizeof($installcfg)) + { + $name = $installcfg['name']; + $copyright = $installcfg['copyright']; + $version = $installcfg['version']; + + $style_row = array( + $mode . '_id' => 0, + $mode . '_name' => '', + $mode . '_copyright' => '' + ); + + switch ($mode) + { + case 'style': + + $style_row = array( + 'style_id' => 0, + 'style_name' => $installcfg['name'], + 'style_copyright' => $installcfg['copyright'] + ); + + $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; + $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; + $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; + + // Check to see if each element is already installed, if it is grab the id + foreach ($element_ary as $element => $table) + { + $style_row = array_merge($style_row, array( + $element . '_id' => 0, + $element . '_name' => '', + $element . '_copyright' => '') + ); + + $this->test_installed($element, $error, (${'reqd_' . $element}) ? PHPBB_ROOT_PATH . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); + + if (!$style_row[$element . '_name']) + { + $style_row[$element . '_name'] = $reqd_template; + } + } + + break; + + case 'template': + $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']); + break; + + case 'theme': + $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']); + break; + + case 'imageset': + $this->test_installed('imageset', $error, $root_path, false, $style_row['imageset_id'], $style_row['imageset_name'], $style_row['imageset_copyright']); + break; + } + } + else + { + trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $style_row['style_active'] = request_var('style_active', 1); + $style_row['style_default'] = request_var('style_default', 0); + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + ${$element . '_root_path'} = (${'reqd_' . $element}) ? PHPBB_ROOT_PATH . 'styles/' . ${'reqd_' . $element} . '/' : false; + ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false; + } + $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path, $imageset_root_path, $imageset_path); + } + else + { + $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright']); + } + + if (!sizeof($error)) + { + $cache->destroy('sql', STYLES_TABLE); + + trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); + } + } + + $this->page_title = 'INSTALL_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_INSTALL' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_THEME' => ($mode == 'theme') ? true : false, + + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + + 'U_ACTION' => $this->u_action . "&action=install&path=" . urlencode($install_path), + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright'], + 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '', + 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '', + 'IMAGESET_NAME' => ($mode == 'style') ? $style_row['imageset_name'] : '') + ); + } + + /** + * Add new style + */ + function add($mode) + { + global $config, $db, $cache, $user, $template; + + $l_type = strtoupper($mode); + $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE, 'imageset' => STYLES_IMAGESET_TABLE); + $error = array(); + + $style_row = array( + $mode . '_name' => utf8_normalize_nfc(request_var('name', '', true)), + $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)), + 'template_id' => 0, + 'theme_id' => 0, + 'imageset_id' => 0, + 'style_active' => request_var('style_active', 1), + 'style_default' => request_var('style_default', 0), + ); + + $basis = request_var('basis', 0); + $update = request::is_set_post('update'); + + if ($basis) + { + switch ($mode) + { + case 'style': + $sql_select = 'template_id, theme_id, imageset_id'; + $sql_from = STYLES_TABLE; + break; + + case 'template': + $sql_select = 'template_id'; + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_select = 'theme_id'; + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_select = 'imageset_id'; + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $sql = "SELECT $sql_select + FROM $sql_from + WHERE {$mode}_id = $basis"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $error[] = $user->lang['NO_' . $l_type]; + } + + if (!sizeof($error)) + { + $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id']; + $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id']; + $style_row['imageset_id'] = (isset($row['imageset_id'])) ? $row['imageset_id'] : $style_row['imageset_id']; + } + } + + if ($update) + { + $style_row['template_id'] = request_var('template_id', $style_row['template_id']); + $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']); + $style_row['imageset_id'] = request_var('imageset_id', $style_row['imageset_id']); + + if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id'])) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + } + + // User has submitted form and no errors have occurred + if ($update && !sizeof($error)) + { + if ($mode == 'style') + { + $style_row['style_id'] = 0; + + $this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row); + } + + if (!sizeof($error)) + { + $cache->destroy('sql', STYLES_TABLE); + + trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action)); + } + } + + if ($mode == 'style') + { + foreach ($element_ary as $element => $table) + { + $sql = "SELECT {$element}_id, {$element}_name + FROM $table + ORDER BY {$element}_id ASC"; + $result = $db->sql_query($sql); + + ${$element . '_options'} = ''; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : ''; + ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>'; + } + $db->sql_freeresult($result); + } + } + + $this->page_title = 'ADD_' . $l_type; + + $template->assign_vars(array( + 'S_DETAILS' => true, + 'S_ADD' => true, + 'S_ERROR_MSG' => (sizeof($error)) ? true : false, + 'S_STYLE' => ($mode == 'style') ? true : false, + 'S_TEMPLATE' => ($mode == 'template') ? true : false, + 'S_THEME' => ($mode == 'theme') ? true : false, + 'S_BASIS' => ($basis) ? true : false, + + 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0, + 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0, + 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '', + 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '', + 'S_IMAGESET_OPTIONS' => ($mode == 'style') ? $imageset_options : '', + + 'U_ACTION' => $this->u_action . '&action=add&basis=' . $basis, + 'U_BACK' => $this->u_action, + + 'L_TITLE' => $user->lang[$this->page_title], + 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'], + 'L_NAME' => $user->lang[$l_type . '_NAME'], + 'L_LOCATION' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION'] : '', + 'L_LOCATION_EXPLAIN' => ($mode == 'template' || $mode == 'theme') ? $user->lang[$l_type . '_LOCATION_EXPLAIN'] : '', + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'NAME' => $style_row[$mode . '_name'], + 'COPYRIGHT' => $style_row[$mode . '_copyright']) + ); + + } + + function generate_stylesheets($theme) + { + global $db, $config; + + // get all the lang_dirs + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $lang_dirs[] = $row['lang_dir']; + } + $db->sql_freeresult($result); + + // get all imagesets this theme is associated with + $sql = 'SELECT si.imageset_id, si.imageset_path, st.template_path + FROM ' . STYLES_TABLE . ' s, ' . STYLES_IMAGESET_TABLE . ' si, ' . STYLES_TEMPLATE_TABLE . ' st + WHERE s.theme_id = ' . (int) $theme['theme_id'] . ' + AND s.imageset_id = si.imageset_id + AND s.template_id = st.template_id'; + $result = $db->sql_query($sql); + while ($theme_row = $db->sql_fetchrow($result)) + { + foreach ($lang_dirs as $lang_dir) + { + $theme['imageset_path'] = $theme_row['imageset_path']; + $theme['imageset_id'] = $theme_row['imageset_id']; + $theme['template_path'] = $theme_row['template_path']; + + $user_image_lang = (file_exists(PHPBB_ROOT_PATH . 'styles/' . $theme['imageset_path'] . '/imageset/' . $lang_dir)) ? $lang_dir : $config['default_lang']; + + // Parse Theme Data + $replace = array( + '{T_THEME_PATH}' => "./styles/" . $theme['theme_path'] . '/theme', + '{T_TEMPLATE_PATH}' => "./styles/" . $theme['template_path'] . '/template', + '{T_IMAGESET_PATH}' => "./styles/" . $theme['imageset_path'] . '/imageset', + '{T_IMAGESET_LANG_PATH}' => "./styles/" . $theme['imageset_path'] . '/imageset/' . $user_image_lang, + '{T_STYLESHEET_NAME}' => $theme['theme_name'], + '{S_USER_LANG}' => $lang_dir // this bastard forces us to make a copy for every language that is installed, not just those with an actual i18'd imageset! + ); + + $sql = 'SELECT image_name, image_filename, image_lang, image_width, image_height + FROM ' . STYLES_IMAGESET_DATA_TABLE . ' + WHERE imageset_id = ' . $theme['imageset_id'] . " + AND image_filename <> '' + AND image_lang IN ('" . $db->sql_escape($user_image_lang) . "', '')"; + $result2 = $db->sql_query($sql); + + $img_array = array(); + while ($row = $db->sql_fetchrow($result2)) + { + $img_array[$row['image_name']] = $row; + } + $db->sql_freeresult($result2); + + $specific_theme_data = str_replace(array_keys($replace), array_values($replace), $theme['theme_data']); + + $matches = array(); + preg_match_all('#\{IMG_([A-Za-z0-9_]*?)_(WIDTH|HEIGHT|SRC)\}#', $specific_theme_data, $matches); + + $imgs = $find = $replace = array(); + if (isset($matches[0]) && sizeof($matches[0])) + { + foreach ($matches[1] as $i => $img) + { + $img = strtolower($img); + $find[] = $matches[0][$i]; + + if (!isset($img_array[$img])) + { + $replace[] = ''; + continue; + } + + if (!isset($imgs[$img])) + { + $img_data = &$img_array[$img]; + $imgsrc = ($img_data['image_lang'] ? $img_data['image_lang'] . '/' : '') . $img_data['image_filename']; + $imgs[$img] = array( + 'src' => './styles/' . $theme['imageset_path'] . '/imageset/' . $imgsrc, + 'width' => $img_data['image_width'], + 'height' => $img_data['image_height'], + ); + } + + switch ($matches[2][$i]) + { + case 'SRC': + $replace[] = $imgs[$img]['src']; + break; + + case 'WIDTH': + $replace[] = $imgs[$img]['width']; + break; + + case 'HEIGHT': + $replace[] = $imgs[$img]['height']; + break; + + default: + continue; + } + } + + if (sizeof($find)) + { + $specific_theme_data = str_replace($find, $replace, $specific_theme_data); + } + } + file_put_contents(PHPBB_ROOT_PATH . '/store/' . $theme['theme_id'] . '_' . $theme['imageset_id'] . '_' . $lang_dir . '.css', $specific_theme_data, LOCK_EX); + } + } + $db->sql_freeresult($result); + } + /** + + $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false; + $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false; + $reqd_imageset = (isset($installcfg['required_imageset'])) ? $installcfg['required_imageset'] : false; + + // Check to see if each element is already installed, if it is grab the id + foreach ($element_ary as $element => $table) + { + $style_row = array_merge($style_row, array( + $element . '_id' => 0, + $element . '_name' => '', + $element . '_copyright' => '') + ); + + $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']); + * Is this element installed? If not, grab its cfg details + */ + function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright) + { + global $db, $user; + + switch ($element) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_element = strtoupper($element); + + $chk_name = ($reqd_name !== false) ? $reqd_name : $name; + + $sql = "SELECT {$element}_id, {$element}_name + FROM $sql_from + WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $name = $row[$element . '_name']; + $id = $row[$element . '_id']; + } + else + { + if (!($cfg = @file("$root_path$element/$element.cfg"))) + { + $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name); + return false; + } + + $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg); + + $name = $cfg['name']; + $copyright = $cfg['copyright']; + $id = 0; + + unset($cfg); + } + $db->sql_freeresult($result); + } + + /** + * Install/Add style + */ + function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false, $imageset_root_path = false, $imageset_path = false) + { + global $config, $db, $user; + + $element_ary = array('template', 'theme', 'imageset'); + + if (!$name) + { + $error[] = $user->lang['STYLE_ERR_STYLE_NAME']; + } + + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang['STYLE_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang['STYLE_ERR_COPY_LONG']; + } + + // Check if the name already exist + $sql = 'SELECT style_id + FROM ' . STYLES_TABLE . " + WHERE style_name = '" . $db->sql_escape($name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $error[] = $user->lang['STYLE_ERR_NAME_EXIST']; + } + + if (sizeof($error)) + { + return false; + } + + foreach ($element_ary as $element) + { + // Zero id value ... need to install element ... run usual checks + // and do the install if necessary + if (!$style_row[$element . '_id']) + { + $this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']); + } + } + + if (!$style_row['template_id'] || !$style_row['theme_id'] || !$style_row['imageset_id']) + { + $error[] = $user->lang['STYLE_ERR_NO_IDS']; + } + + if (sizeof($error)) + { + return false; + } + + $db->sql_transaction('begin'); + + $sql_ary = array( + 'style_name' => $name, + 'style_copyright' => $copyright, + 'style_active' => (int) $active, + 'template_id' => (int) $style_row['template_id'], + 'theme_id' => (int) $style_row['theme_id'], + 'imageset_id' => (int) $style_row['imageset_id'], + ); + + $sql = 'INSERT INTO ' . STYLES_TABLE . ' + ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $id = $db->sql_nextid(); + + if ($default) + { + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_style = $id + WHERE user_style = " . $config['default_style']; + $db->sql_query($sql); + + set_config('default_style', $id); + } + + $db->sql_transaction('commit'); + + add_log('admin', 'LOG_STYLE_ADD', $name); + } + + /** + * Install/add an element, doing various checks as we go + */ + function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright, $store_db = 0) + { + global $db, $user; + + switch ($mode) + { + case 'template': + $sql_from = STYLES_TEMPLATE_TABLE; + break; + + case 'theme': + $sql_from = STYLES_THEME_TABLE; + break; + + case 'imageset': + $sql_from = STYLES_IMAGESET_TABLE; + break; + } + + $l_type = strtoupper($mode); + + if (!$name) + { + $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME']; + } + + // Check length settings + if (utf8_strlen($name) > 30) + { + $error[] = $user->lang[$l_type . '_ERR_NAME_LONG']; + } + + if (utf8_strlen($copyright) > 60) + { + $error[] = $user->lang[$l_type . '_ERR_COPY_LONG']; + } + + // Check if the name already exist + $sql = "SELECT {$mode}_id + FROM $sql_from + WHERE {$mode}_name = '" . $db->sql_escape($name) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + + if ($row) + { + // If it exist, we just use the style on installation + if ($action == 'install') + { + $id = $row[$mode . '_id']; + return false; + } + + $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST']; + } + + if (sizeof($error)) + { + return false; + } + + $sql_ary = array( + $mode . '_name' => $name, + $mode . '_copyright' => $copyright, + $mode . '_path' => $path, + ); + + switch ($mode) + { + case 'template': + // We check if the template author defined a different bitfield + $cfg_data = parse_cfg_file("$root_path$mode/template.cfg"); + + if (!empty($cfg_data['template_bitfield'])) + { + $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield']; + } + else + { + $sql_ary['bbcode_bitfield'] = TEMPLATE_BITFIELD; + } + break; + + case 'theme': + // We are only interested in the theme configuration for now + $theme_cfg = parse_cfg_file(PHPBB_ROOT_PATH . "styles/$path/theme/theme.cfg"); + + if (isset($theme_cfg['parse_css_file']) && $theme_cfg['parse_css_file']) + { + $store_db = 1; + } + + $sql_ary += array( + 'theme_storedb' => $store_db, + 'theme_data' => ($store_db) ? $this->db_theme_data($sql_ary, false, $root_path) : '', + 'theme_mtime' => (int) filemtime(PHPBB_ROOT_PATH . "styles/$path/theme/stylesheet.css") + ); + break; + + // all the heavy lifting is done later + case 'imageset': + break; + } + + $db->sql_transaction('begin'); + + $sql = "INSERT INTO $sql_from + " . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $id = $db->sql_nextid(); + + if ($mode == 'imageset') + { + $cfg_data = parse_cfg_file("$root_path$mode/imageset.cfg"); + + $imageset_definitions = array(); + foreach ($this->imageset_keys as $topic => $key_array) + { + $imageset_definitions = array_merge($imageset_definitions, $key_array); + } + + foreach ($cfg_data as $key => $value) + { + if (strpos($value, '*') !== false) + { + if (substr($value, -1, 1) === '*') + { + list($image_filename, $image_height) = explode('*', $value); + $image_width = 0; + } + else + { + list($image_filename, $image_height, $image_width) = explode('*', $value); + } + } + else + { + $image_filename = $value; + $image_height = $image_width = 0; + } + + if (strpos($key, 'img_') === 0 && $image_filename) + { + $key = substr($key, 4); + if (in_array($key, $imageset_definitions)) + { + $sql_ary = array( + 'image_name' => $key, + 'image_filename' => str_replace('{PATH}', "styles/$path/imageset/", trim($image_filename)), + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $id, + 'image_lang' => '', + ); + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + } + unset($cfg_data); + + $sql = 'SELECT lang_dir + FROM ' . LANG_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (@file_exists("$root_path$mode/{$row['lang_dir']}/imageset.cfg")) + { + $cfg_data_imageset_data = parse_cfg_file("$root_path$mode/{$row['lang_dir']}/imageset.cfg"); + foreach ($cfg_data_imageset_data as $image_name => $value) + { + if (strpos($value, '*') !== false) + { + if (substr($value, -1, 1) === '*') + { + list($image_filename, $image_height) = explode('*', $value); + $image_width = 0; + } + else + { + list($image_filename, $image_height, $image_width) = explode('*', $value); + } + } + else + { + $image_filename = $value; + $image_height = $image_width = 0; + } + + if (strpos($image_name, 'img_') === 0 && $image_filename) + { + $image_name = substr($image_name, 4); + if (in_array($image_name, $imageset_definitions)) + { + $sql_ary = array( + 'image_name' => $image_name, + 'image_filename' => $image_filename, + 'image_height' => (int) $image_height, + 'image_width' => (int) $image_width, + 'imageset_id' => (int) $id, + 'image_lang' => $row['lang_dir'], + ); + $db->sql_query('INSERT INTO ' . STYLES_IMAGESET_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + } + unset($cfg_data_imageset_data); + } + } + $db->sql_freeresult($result); + } + + $db->sql_transaction('commit'); + + $log = ($store_db) ? 'LOG_' . $l_type . '_ADD_DB' : 'LOG_' . $l_type . '_ADD_FS'; + add_log('admin', $log, $name); + + // Return store_db in case it had to be altered + return $store_db; + } +} + +?> diff --git a/phpBB/modules/acp/acp_update.php b/phpBB/modules/acp/acp_update.php new file mode 100644 index 0000000000..a6440c8364 --- /dev/null +++ b/phpBB/modules/acp/acp_update.php @@ -0,0 +1,80 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_update +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + $user->add_lang('install'); + + $this->tpl_name = 'acp_update'; + $this->page_title = 'ACP_VERSION_CHECK'; + + // Get current and latest version + $errstr = ''; + $errno = 0; + + $info = get_remote_file('www.phpbb.com', '/updatecheck', ((defined('PHPBB_QA')) ? '30x_qa.txt' : '30x.txt'), $errstr, $errno); + + if ($info === false) + { + trigger_error($errstr, E_USER_WARNING); + } + + $info = explode("\n", $info); + $latest_version = trim($info[0]); + + $announcement_url = trim($info[1]); + $update_link = append_sid('install/index', 'mode=update'); + + // Determine automatic update... + $sql = 'SELECT config_value + FROM ' . CONFIG_TABLE . " + WHERE config_name = 'version_update_from'"; + $result = $db->sql_query($sql); + $version_update_from = (string) $db->sql_fetchfield('config_value'); + $db->sql_freeresult($result); + + $current_version = (!empty($version_update_from)) ? $version_update_from : $config['version']; + + $up_to_date_automatic = (version_compare(str_replace('rc', 'RC', strtolower($current_version)), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true; + $up_to_date = (version_compare(str_replace('rc', 'RC', strtolower($config['version'])), str_replace('rc', 'RC', strtolower($latest_version)), '<')) ? false : true; + + $template->assign_vars(array( + 'S_UP_TO_DATE' => $up_to_date, + 'S_UP_TO_DATE_AUTO' => $up_to_date_automatic, + 'S_VERSION_CHECK' => true, + 'U_ACTION' => $this->u_action, + + 'LATEST_VERSION' => $latest_version, + 'CURRENT_VERSION' => $config['version'], + 'AUTO_VERSION' => $version_update_from, + + 'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $announcement_url, $update_link), + )); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_users.php b/phpBB/modules/acp/acp_users.php new file mode 100644 index 0000000000..395e07751d --- /dev/null +++ b/phpBB/modules/acp/acp_users.php @@ -0,0 +1,2089 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package acp +*/ +class acp_users +{ + var $u_action; + var $p_master; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache, $file_uploads; + + $user->add_lang(array('posting', 'ucp', 'acp/users')); + $this->tpl_name = 'acp_users'; + $this->page_title = 'ACP_USER_' . strtoupper($mode); + + $error = array(); + $username = utf8_normalize_nfc(request_var('username', '', true)); + $user_id = request_var('u', 0); + $action = request_var('action', ''); + + $submit = (request::is_set_post('update') && !request::is_set_post('cancel')) ? true : false; + + $form_name = 'acp_users'; + add_form_key($form_name); + + // Whois (special case) + if ($action == 'whois') + { + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $this->page_title = 'WHOIS'; + $this->tpl_name = 'simple_body'; + + $user_ip = request_var('user_ip', ''); + $domain = gethostbyaddr($user_ip); + $ipwhois = user_ipwhois($user_ip); + + $template->assign_vars(array( + 'MESSAGE_TITLE' => sprintf($user->lang['IP_WHOIS_FOR'], $domain), + 'MESSAGE_TEXT' => nl2br($ipwhois)) + ); + + return; + } + + // Show user selection mask + if (!$username && !$user_id) + { + $this->page_title = 'SELECT_USER'; + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'ANONYMOUS_USER_ID' => ANONYMOUS, + + 'S_SELECT_USER' => true, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=select_user&field=username&select_single=true'), + )); + + return; + } + + if (!$user_id) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_id = (int) $db->sql_fetchfield('user_id'); + $db->sql_freeresult($result); + + if (!$user_id) + { + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + } + + // Generate content for all modes + $sql = 'SELECT u.*, s.* + FROM ' . USERS_TABLE . ' u + LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id) + WHERE u.user_id = ' . $user_id . ' + ORDER BY s.session_time DESC'; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error($user->lang['NO_USER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + // Generate overall "header" for user admin + $s_form_options = ''; + + // Build modes dropdown list + $sql = 'SELECT module_mode, module_auth + FROM ' . MODULES_TABLE . " + WHERE module_basename = 'users' + AND module_enabled = 1 + AND module_class = 'acp' + ORDER BY left_id, module_mode"; + $result = $db->sql_query($sql); + + $dropdown_modes = array(); + while ($row = $db->sql_fetchrow($result)) + { + if (!$this->p_master->module_auth($row['module_auth'])) + { + continue; + } + + $dropdown_modes[$row['module_mode']] = true; + } + $db->sql_freeresult($result); + + foreach ($dropdown_modes as $module_mode => $null) + { + $selected = ($mode == $module_mode) ? ' selected="selected"' : ''; + $s_form_options .= '<option value="' . $module_mode . '"' . $selected . '>' . $user->lang['ACP_USER_' . strtoupper($module_mode)] . '</option>'; + } + + $template->assign_vars(array( + 'U_BACK' => $this->u_action, + 'U_MODE_SELECT' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=$id&u=$user_id"), + 'U_ACTION' => $this->u_action . '&u=' . $user_id, + 'S_FORM_OPTIONS' => $s_form_options, + 'MANAGED_USERNAME' => $user_row['username']) + ); + + // Prevent normal users/admins change/view founders if they are not a founder by themselves + if ($user->data['user_type'] != USER_FOUNDER && $user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['NOT_MANAGE_FOUNDER'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + switch ($mode) + { + case 'overview': + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $user->add_lang('acp/ban'); + + $delete = request_var('delete', 0); + $delete_type = request_var('delete_type', ''); + $ip = request_var('ip', 'ip'); + + if ($submit) + { + // You can't delete the founder + if ($delete && $user_row['user_type'] != USER_FOUNDER) + { + if (!$auth->acl_get('a_userdel')) + { + trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Check if the user wants to remove himself or the guest user account + if ($user_id == ANONYMOUS) + { + trigger_error($user->lang['CANNOT_REMOVE_ANONYMOUS'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_REMOVE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (confirm_box(true)) + { + user_delete($delete_type, $user_id, $user_row['username']); + + add_log('admin', 'LOG_USER_DELETED', $user_row['username']); + trigger_error($user->lang['USER_DELETED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true, + 'delete' => 1, + 'delete_type' => $delete_type)) + ); + } + } + + // Handle quicktool actions + switch ($action) + { + case 'banuser': + case 'banemail': + case 'banip': + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_BAN_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_BAN_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $ban = array(); + + switch ($action) + { + case 'banuser': + $ban[] = $user_row['username']; + $reason = 'USER_ADMIN_BAN_NAME_REASON'; + $log = 'LOG_USER_BAN_USER'; + break; + + case 'banemail': + $ban[] = $user_row['user_email']; + $reason = 'USER_ADMIN_BAN_EMAIL_REASON'; + $log = 'LOG_USER_BAN_EMAIL'; + break; + + case 'banip': + $ban[] = $user_row['user_ip']; + + $sql = 'SELECT DISTINCT poster_ip + FROM ' . POSTS_TABLE . " + WHERE poster_id = $user_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $ban[] = $row['poster_ip']; + } + $db->sql_freeresult($result); + + $reason = 'USER_ADMIN_BAN_IP_REASON'; + $log = 'LOG_USER_BAN_IP'; + break; + } + + $ban_reason = utf8_normalize_nfc(request_var('ban_reason', $user->lang[$reason], true)); + $ban_give_reason = utf8_normalize_nfc(request_var('ban_give_reason', '', true)); + + // Log not used at the moment, we simply utilize the ban function. + $result = user_ban(substr($action, 3), $ban, 0, 0, 0, $ban_reason, $ban_give_reason); + + trigger_error((($result === false) ? $user->lang['BAN_ALREADY_ENTERED'] : $user->lang['BAN_SUCCESSFUL']) . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'reactivate': + + if ($user_id == $user->data['user_id']) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_FORCE_REACT_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($config['email_enable']) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $server_url = generate_board_url(); + + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len > 6) ? $key_len : 6; + $user_actkey = substr($user_actkey, 0, $key_len); + $email_template = ($user_row['user_type'] == USER_NORMAL) ? 'user_reactivate_account' : 'user_resend_inactive'; + + if ($user_row['user_type'] == USER_NORMAL) + { + user_active_flip('deactivate', $user_id, INACTIVE_REMIND); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = $user_id"; + $db->sql_query($sql); + } + else + { + // Grabbing the last confirm key - we only send a reminder + $sql = 'SELECT user_actkey + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + $user_actkey = (string) $db->sql_fetchfield('user_actkey'); + $db->sql_freeresult($result); + } + + $messenger = new messenger(false); + + $messenger->template($email_template, $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u={$user_row['user_id']}&k=$user_actkey") + ); + + $messenger->send(NOTIFY_EMAIL); + + add_log('admin', 'LOG_USER_REACTIVATE', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_REACTIVATE_USER'); + + trigger_error($user->lang['FORCE_REACTIVATION_SUCCESS'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + break; + + case 'active': + + if ($user_id == $user->data['user_id']) + { + // It is only deactivation since the user is already activated (else he would not have reached this page) + trigger_error($user->lang['CANNOT_DEACTIVATE_YOURSELF'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_FOUNDER) + { + trigger_error($user->lang['CANNOT_DEACTIVATE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_DEACTIVATE_BOT'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + user_active_flip('flip', $user_id); + + $message = ($user_row['user_type'] == USER_INACTIVE) ? 'USER_ADMIN_ACTIVATED' : 'USER_ADMIN_DEACTIVED'; + $log = ($user_row['user_type'] == USER_INACTIVE) ? 'LOG_USER_ACTIVE' : 'LOG_USER_INACTIVE'; + + add_log('admin', $log, $user_row['username']); + add_log('user', $user_id, $log . '_USER'); + + trigger_error($user->lang[$message] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'delsig': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary = array( + 'user_sig' => '', + 'user_sig_bbcode_uid' => '', + 'user_sig_bbcode_bitfield' => '' + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + add_log('admin', 'LOG_USER_DEL_SIG', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_DEL_SIG_USER'); + + trigger_error($user->lang['USER_ADMIN_SIG_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + + case 'delavatar': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary = array( + 'user_avatar' => '', + 'user_avatar_type' => 0, + 'user_avatar_width' => 0, + 'user_avatar_height' => 0, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + // Delete old avatar if present + if ($user_row['user_avatar'] && $user_row['user_avatar_type'] != AVATAR_GALLERY) + { + avatar_delete('user', $user_row); + } + + add_log('admin', 'LOG_USER_DEL_AVATAR', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_DEL_AVATAR_USER'); + + trigger_error($user->lang['USER_ADMIN_AVATAR_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + break; + + case 'delposts': + + if (confirm_box(true)) + { + // Delete posts, attachments, etc. + delete_posts('poster_id', $user_id); + + add_log('admin', 'LOG_USER_DEL_POSTS', $user_row['username']); + trigger_error($user->lang['USER_POSTS_DELETED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + + break; + + case 'delattach': + + if (confirm_box(true)) + { + delete_attachments('user', $user_id); + + add_log('admin', 'LOG_USER_DEL_ATTACH', $user_row['username']); + trigger_error($user->lang['USER_ATTACHMENTS_REMOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'update' => true)) + ); + } + + break; + + case 'moveposts': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $user->add_lang('acp/forums'); + + $new_forum_id = request_var('new_f', 0); + + if (!$new_forum_id) + { + $this->page_title = 'USER_ADMIN_MOVE_POSTS'; + + $template->assign_vars(array( + 'S_SELECT_FORUM' => true, + 'U_ACTION' => $this->u_action . "&action=$action&u=$user_id", + 'U_BACK' => $this->u_action . "&u=$user_id", + 'S_FORUM_OPTIONS' => make_forum_select(false, false, false, true)) + ); + + return; + } + + // Is the new forum postable to? + $sql = 'SELECT forum_name, forum_type + FROM ' . FORUMS_TABLE . " + WHERE forum_id = $new_forum_id"; + $result = $db->sql_query($sql); + $forum_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$forum_info) + { + trigger_error($user->lang['NO_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($forum_info['forum_type'] != FORUM_POST) + { + trigger_error($user->lang['MOVE_POSTS_NO_POSTABLE_FORUM'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Two stage? + // Move topics comprising only posts from this user + $topic_id_ary = $move_topic_ary = $move_post_ary = $new_topic_id_ary = array(); + $forum_id_ary = array($new_forum_id); + + $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts + FROM ' . POSTS_TABLE . " + WHERE poster_id = $user_id + AND forum_id <> $new_forum_id + GROUP BY topic_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_ary[$row['topic_id']] = $row['total_posts']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_id_ary)) + { + $sql = 'SELECT topic_id, forum_id, topic_title, topic_replies, topic_replies_real, topic_attachment + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', array_keys($topic_id_ary)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) + { + $move_topic_ary[] = $row['topic_id']; + } + else + { + $move_post_ary[$row['topic_id']]['title'] = $row['topic_title']; + $move_post_ary[$row['topic_id']]['attach'] = ($row['topic_attachment']) ? 1 : 0; + } + + $forum_id_ary[] = $row['forum_id']; + } + $db->sql_freeresult($result); + } + + // Entire topic comprises posts by this user, move these topics + if (sizeof($move_topic_ary)) + { + move_topics($move_topic_ary, $new_forum_id, false); + } + + if (sizeof($move_post_ary)) + { + // Create new topic + // Update post_ids, report_ids, attachment_ids + foreach ($move_post_ary as $topic_id => $post_ary) + { + // Create new topic + $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'topic_poster' => $user_id, + 'topic_time' => time(), + 'forum_id' => $new_forum_id, + 'icon_id' => 0, + 'topic_approved' => 1, + 'topic_title' => $post_ary['title'], + 'topic_first_poster_name' => $user_row['username'], + 'topic_type' => POST_NORMAL, + 'topic_time_limit' => 0, + 'topic_attachment' => $post_ary['attach']) + ); + $db->sql_query($sql); + + $new_topic_id = $db->sql_nextid(); + + // Move posts + $sql = 'UPDATE ' . POSTS_TABLE . " + SET forum_id = $new_forum_id, topic_id = $new_topic_id + WHERE topic_id = $topic_id + AND poster_id = $user_id"; + $db->sql_query($sql); + + if ($post_ary['attach']) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " + SET topic_id = $new_topic_id + WHERE topic_id = $topic_id + AND poster_id = $user_id"; + $db->sql_query($sql); + } + + $new_topic_id_ary[] = $new_topic_id; + } + } + + $forum_id_ary = array_unique($forum_id_ary); + $topic_id_ary = array_unique(array_merge(array_keys($topic_id_ary), $new_topic_id_ary)); + + if (sizeof($topic_id_ary)) + { + sync('topic_reported', 'topic_id', $topic_id_ary); + sync('topic', 'topic_id', $topic_id_ary); + } + + if (sizeof($forum_id_ary)) + { + sync('forum', 'forum_id', $forum_id_ary, false, true); + } + + + add_log('admin', 'LOG_USER_MOVE_POSTS', $user_row['username'], $forum_info['forum_name']); + add_log('user', $user_id, 'LOG_USER_MOVE_POSTS_USER', $forum_info['forum_name']); + + trigger_error($user->lang['USER_POSTS_MOVED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + + break; + } + + // Handle registration info updates + $data = array( + 'username' => utf8_normalize_nfc(request_var('user', $user_row['username'], true)), + 'user_founder' => request_var('user_founder', ($user_row['user_type'] == USER_FOUNDER) ? 1 : 0), + 'email' => strtolower(request_var('user_email', $user_row['user_email'])), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'new_password' => request_var('new_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + ); + + // Validation data - we do not check the password complexity setting here + $check_ary = array( + 'new_password' => array( + array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + ); + + // Check username if altered + if ($data['username'] != $user_row['username']) + { + $check_ary += array( + 'username' => array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username', $user_row['username']) + ), + ); + } + + // Check email if altered + if ($data['email'] != $user_row['user_email']) + { + $check_ary += array( + 'email' => array( + array('string', false, 6, 60), + array('email', $user_row['user_email']) + ), + 'email_confirm' => array('string', true, 6, 60) + ); + } + + $error = validate_data($data, $check_ary); + + if ($data['new_password'] && $data['password_confirm'] != $data['new_password']) + { + $error[] = 'NEW_PASSWORD_ERROR'; + } + + if ($data['email'] != $user_row['user_email'] && $data['email_confirm'] != $data['email']) + { + $error[] = 'NEW_EMAIL_ERROR'; + } + + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + // Which updates do we need to do? + $update_username = ($user_row['username'] != $data['username']) ? $data['username'] : false; + $update_password = ($data['new_password'] && !phpbb_check_hash($user_row['user_password'], $data['new_password'])) ? true : false; + $update_email = ($data['email'] != $user_row['user_email']) ? $data['email'] : false; + + if (!sizeof($error)) + { + $sql_ary = array(); + + if ($user_row['user_type'] != USER_FOUNDER || $user->data['user_type'] == USER_FOUNDER) + { + // Only allow founders updating the founder status... + if ($user->data['user_type'] == USER_FOUNDER) + { + // Setting a normal member to be a founder + if ($data['user_founder'] && $user_row['user_type'] != USER_FOUNDER) + { + // Make sure the user is not setting an Inactive or ignored user to be a founder + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error($user->lang['CANNOT_SET_FOUNDER_IGNORED'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($user_row['user_type'] == USER_INACTIVE) + { + trigger_error($user->lang['CANNOT_SET_FOUNDER_INACTIVE'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $sql_ary['user_type'] = USER_FOUNDER; + } + else if (!$data['user_founder'] && $user_row['user_type'] == USER_FOUNDER) + { + // Check if at least one founder is present + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE user_type = ' . USER_FOUNDER . ' + AND user_id <> ' . $user_id; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $sql_ary['user_type'] = USER_NORMAL; + } + else + { + trigger_error($user->lang['AT_LEAST_ONE_FOUNDER'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + } + } + } + + if ($update_username !== false) + { + $sql_ary['username'] = $update_username; + $sql_ary['username_clean'] = utf8_clean_string($update_username); + + add_log('user', $user_id, 'LOG_USER_UPDATE_NAME', $user_row['username'], $update_username); + } + + if ($update_email !== false) + { + $sql_ary += array( + 'user_email' => $update_email, + 'user_email_hash' => hexdec(crc32($update_email) . strlen($update_email)) + ); + + add_log('user', $user_id, 'LOG_USER_UPDATE_EMAIL', $user_row['username'], $user_row['user_email'], $update_email); + } + + if ($update_password) + { + $sql_ary += array( + 'user_password' => phpbb_hash($data['new_password']), + 'user_passchg' => time(), + 'user_pass_convert' => 0, + ); + + $user->reset_login_keys($user_id); + add_log('user', $user_id, 'LOG_USER_NEW_PASSWORD', $user_row['username']); + } + + if (sizeof($sql_ary)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + } + + if ($update_username) + { + user_update_name($user_row['username'], $update_username); + } + + // Let the users permissions being updated + $auth->acl_clear_prefetch($user_id); + + add_log('admin', 'LOG_USER_USER_UPDATE', $data['username']); + + trigger_error($user->lang['USER_OVERVIEW_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if ($user_id == $user->data['user_id']) + { + $quick_tool_ary = array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH'); + } + else + { + $quick_tool_ary = array(); + + if ($user_row['user_type'] != USER_FOUNDER) + { + $quick_tool_ary += array('banuser' => 'BAN_USER', 'banemail' => 'BAN_EMAIL', 'banip' => 'BAN_IP'); + } + + if ($user_row['user_type'] != USER_FOUNDER && $user_row['user_type'] != USER_IGNORE) + { + $quick_tool_ary += array('active' => (($user_row['user_type'] == USER_INACTIVE) ? 'ACTIVATE' : 'DEACTIVATE')); + } + + $quick_tool_ary += array('delsig' => 'DEL_SIG', 'delavatar' => 'DEL_AVATAR', 'moveposts' => 'MOVE_POSTS', 'delposts' => 'DEL_POSTS', 'delattach' => 'DEL_ATTACH'); + + if ($config['email_enable'] && ($user_row['user_type'] == USER_NORMAL || $user_row['user_type'] == USER_INACTIVE)) + { + $quick_tool_ary['reactivate'] = 'FORCE'; + } + } + + $s_action_options = '<option class="sep" value="">' . $user->lang['SELECT_OPTION'] . '</option>'; + foreach ($quick_tool_ary as $value => $lang) + { + $s_action_options .= '<option value="' . $value . '">' . $user->lang['USER_ADMIN_' . $lang] . '</option>'; + } + + if ($config['load_onlinetrack']) + { + $sql = 'SELECT MAX(session_time) AS session_time, MIN(session_viewonline) AS session_viewonline + FROM ' . SESSIONS_TABLE . " + WHERE session_user_id = $user_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $user_row['session_time'] = (isset($row['session_time'])) ? $row['session_time'] : 0; + $user_row['session_viewonline'] = (isset($row['session_viewonline'])) ? $row['session_viewonline'] : 0; + unset($row); + } + + $last_visit = (!empty($user_row['session_time'])) ? $user_row['session_time'] : $user_row['user_lastvisit']; + + $inactive_reason = ''; + if ($user_row['user_type'] == USER_INACTIVE) + { + $inactive_reason = $user->lang['INACTIVE_REASON_UNKNOWN']; + + switch ($user_row['user_inactive_reason']) + { + case INACTIVE_REGISTER: + $inactive_reason = $user->lang['INACTIVE_REASON_REGISTER']; + break; + + case INACTIVE_PROFILE: + $inactive_reason = $user->lang['INACTIVE_REASON_PROFILE']; + break; + + case INACTIVE_MANUAL: + $inactive_reason = $user->lang['INACTIVE_REASON_MANUAL']; + break; + + case INACTIVE_REMIND: + $inactive_reason = $user->lang['INACTIVE_REASON_REMIND']; + break; + } + } + + // Posts in Queue + $sql = 'SELECT COUNT(post_id) as posts_in_queue + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND post_approved = 0'; + $result = $db->sql_query($sql); + $user_row['posts_in_queue'] = (int) $db->sql_fetchfield('posts_in_queue'); + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_NAME_CHARS_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + 'L_POSTS_IN_QUEUE' => $user->lang('NUM_POSTS_IN_QUEUE', $user_row['posts_in_queue']), + 'S_FOUNDER' => ($user->data['user_type'] == USER_FOUNDER) ? true : false, + + 'S_OVERVIEW' => true, + 'S_USER_IP' => ($user_row['user_ip']) ? true : false, + 'S_USER_FOUNDER' => ($user_row['user_type'] == USER_FOUNDER) ? true : false, + 'S_ACTION_OPTIONS' => $s_action_options, + 'S_OWN_ACCOUNT' => ($user_id == $user->data['user_id']) ? true : false, + 'S_USER_INACTIVE' => ($user_row['user_type'] == USER_INACTIVE) ? true : false, + + 'U_SHOW_IP' => $this->u_action . "&u=$user_id&ip=" . (($ip == 'ip') ? 'hostname' : 'ip'), + 'U_WHOIS' => $this->u_action . "&action=whois&user_ip={$user_row['user_ip']}", + 'U_MCP_QUEUE' => ($auth->acl_getf_global('m_approve')) ? append_sid('mcp', 'i=queue', true, $user->session_id) : '', + + 'U_SWITCH_PERMISSIONS' => ($auth->acl_get('a_switchperm') && $user->data['user_id'] != $user_row['user_id']) ? append_sid('ucp', "mode=switch_perm&u={$user_row['user_id']}") : '', + + 'POSTS_IN_QUEUE' => $user_row['posts_in_queue'], + 'USER' => $user_row['username'], + 'USER_REGISTERED' => $user->format_date($user_row['user_regdate']), + 'REGISTERED_IP' => ($ip == 'hostname') ? gethostbyaddr($user_row['user_ip']) : $user_row['user_ip'], + 'USER_LASTACTIVE' => ($last_visit) ? $user->format_date($last_visit) : ' - ', + 'USER_EMAIL' => $user_row['user_email'], + 'USER_WARNINGS' => $user_row['user_warnings'], + 'USER_POSTS' => $user_row['user_posts'], + 'USER_INACTIVE_REASON' => $inactive_reason, + )); + + break; + + case 'feedback': + + $user->add_lang('mcp'); + + // Set up general vars + $start = request_var('start', 0); + $deletemark = request::is_set_post('delmarked'); + $deleteall = request::is_set_post('delall'); + $marked = request_var('mark', array(0)); + $message = utf8_normalize_nfc(request_var('message', '', true)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $where_sql = ''; + if ($deletemark && $marked) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_USERS . " + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_USER', $user_row['username']); + } + } + + if ($submit && $message) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + add_log('admin', 'LOG_USER_FEEDBACK', $user_row['username']); + add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $user_row['username']); + add_log('user', $user_id, 'LOG_USER_GENERAL', $message); + + trigger_error($user->lang['USER_FEEDBACK_ADDED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['topics_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort); + + $template->assign_vars(array( + 'S_FEEDBACK' => true, + 'S_ON_PAGE' => on_page($log_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&u=$user_id&$u_sort_param", $log_count, $config['topics_per_page'], $start, true), + + 'S_LIMIT_DAYS' => $s_limit_days, + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + 'S_CLEARLOGS' => $auth->acl_get('a_clearlogs')) + ); + + foreach ($log_data as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => nl2br($row['action']), + 'ID' => $row['id']) + ); + } + + break; + + case 'profile': + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); + + $cp = new custom_profile(); + + $cp_data = $cp_error = array(); + + $sql = 'SELECT lang_id + FROM ' . LANG_TABLE . " + WHERE lang_iso = '" . $db->sql_escape($user->data['user_lang']) . "'"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $user_row['iso_lang_id'] = $row['lang_id']; + + $data = array( + 'icq' => request_var('icq', $user_row['user_icq']), + 'aim' => request_var('aim', $user_row['user_aim']), + 'msn' => request_var('msn', $user_row['user_msnm']), + 'yim' => request_var('yim', $user_row['user_yim']), + 'jabber' => utf8_normalize_nfc(request_var('jabber', $user_row['user_jabber'], true)), + 'website' => request_var('website', $user_row['user_website']), + 'location' => utf8_normalize_nfc(request_var('location', $user_row['user_from'], true)), + 'occupation' => utf8_normalize_nfc(request_var('occupation', $user_row['user_occ'], true)), + 'interests' => utf8_normalize_nfc(request_var('interests', $user_row['user_interests'], true)), + 'bday_day' => 0, + 'bday_month' => 0, + 'bday_year' => 0, + ); + + if ($user_row['user_birthday']) + { + list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user_row['user_birthday']); + } + + $data['bday_day'] = request_var('bday_day', $data['bday_day']); + $data['bday_month'] = request_var('bday_month', $data['bday_month']); + $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); + + + if ($submit) + { + $error = validate_data($data, array( + 'icq' => array( + array('string', true, 3, 15), + array('match', true, '#^[0-9]+$#i')), + 'aim' => array('string', true, 3, 255), + 'msn' => array('string', true, 5, 255), + 'jabber' => array( + array('string', true, 5, 255), + array('jabber')), + 'yim' => array('string', true, 5, 255), + 'website' => array( + array('string', true, 12, 255), + array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), + 'location' => array('string', true, 2, 100), + 'occupation' => array('string', true, 2, 500), + 'interests' => array('string', true, 2, 500), + 'bday_day' => array('num', true, 1, 31), + 'bday_month' => array('num', true, 1, 12), + 'bday_year' => array('num', true, 1901, gmdate('Y', time())), + 'user_birthday' => array('date', true), + )); + + // validate custom profile fields + $cp->submit_cp_field('profile', $user_row['iso_lang_id'], $cp_data, $cp_error); + + if (sizeof($cp_error)) + { + $error = array_merge($error, $cp_error); + } + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $sql_ary = array( + 'user_icq' => $data['icq'], + 'user_aim' => $data['aim'], + 'user_msnm' => $data['msn'], + 'user_yim' => $data['yim'], + 'user_jabber' => $data['jabber'], + 'user_website' => $data['website'], + 'user_from' => $data['location'], + 'user_occ' => $data['occupation'], + 'user_interests'=> $data['interests'], + 'user_birthday' => $data['user_birthday'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + // Update Custom Fields + if (sizeof($cp_data)) + { + switch ($db->dbms_type) + { + case 'oracle': + case 'firebird': + case 'postgres': + case 'db2': + $right_delim = $left_delim = '"'; + break; + + case 'sqlite': + case 'mssql': + $right_delim = ']'; + $left_delim = '['; + break; + + case 'mysql': + $right_delim = $left_delim = '`'; + break; + } + + foreach ($cp_data as $key => $value) + { + $cp_data[$left_delim . $key . $right_delim] = $value; + unset($cp_data[$key]); + } + + $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $cp_data) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + if (!$db->sql_affectedrows()) + { + $cp_data['user_id'] = (int) $user_id; + + $db->sql_return_on_error(true); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data); + $db->sql_query($sql); + + $db->sql_return_on_error(false); + } + } + + trigger_error($user->lang['USER_PROFILE_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 32; $i++) + { + $selected = ($i == $data['bday_day']) ? ' selected="selected"' : ''; + $s_birthday_day_options .= "<option value=\"$i\"$selected>$i</option>"; + } + + $s_birthday_month_options = '<option value="0"' . ((!$data['bday_month']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 13; $i++) + { + $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; + $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; + } + $s_birthday_year_options = ''; + + $now = getdate(); + $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = $now['year'] - 100; $i < $now['year']; $i++) + { + $selected = ($i == $data['bday_year']) ? ' selected="selected"' : ''; + $s_birthday_year_options .= "<option value=\"$i\"$selected>$i</option>"; + } + unset($now); + + $template->assign_vars(array( + 'ICQ' => $data['icq'], + 'YIM' => $data['yim'], + 'AIM' => $data['aim'], + 'MSN' => $data['msn'], + 'JABBER' => $data['jabber'], + 'WEBSITE' => $data['website'], + 'LOCATION' => $data['location'], + 'OCCUPATION' => $data['occupation'], + 'INTERESTS' => $data['interests'], + + 'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options, + 'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options, + 'S_BIRTHDAY_YEAR_OPTIONS' => $s_birthday_year_options, + + 'S_PROFILE' => true) + ); + + // Get additional profile fields and assign them to the template block var 'profile_fields' + $user->get_profile_fields($user_id); + + $cp->generate_profile_fields('profile', $user_row['iso_lang_id']); + + break; + + case 'prefs': + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $data = array( + 'dateformat' => utf8_normalize_nfc(request_var('dateformat', $user_row['user_dateformat'], true)), + 'lang' => basename(request_var('lang', $user_row['user_lang'])), + 'tz' => request_var('tz', (float) $user_row['user_timezone']), + 'style' => request_var('style', $user_row['user_style']), + 'dst' => request_var('dst', $user_row['user_dst']), + 'viewemail' => request_var('viewemail', $user_row['user_allow_viewemail']), + 'massemail' => request_var('massemail', $user_row['user_allow_massemail']), + 'hideonline' => request_var('hideonline', !$user_row['user_allow_viewonline']), + 'notifymethod' => request_var('notifymethod', $user_row['user_notify_type']), + 'notifypm' => request_var('notifypm', $user_row['user_notify_pm']), + 'popuppm' => request_var('popuppm', $this->optionget($user_row, 'popuppm')), + 'allowpm' => request_var('allowpm', $user_row['user_allow_pm']), + + 'topic_sk' => request_var('topic_sk', ($user_row['user_topic_sortby_type']) ? $user_row['user_topic_sortby_type'] : 't'), + 'topic_sd' => request_var('topic_sd', ($user_row['user_topic_sortby_dir']) ? $user_row['user_topic_sortby_dir'] : 'd'), + 'topic_st' => request_var('topic_st', ($user_row['user_topic_show_days']) ? $user_row['user_topic_show_days'] : 0), + + 'post_sk' => request_var('post_sk', ($user_row['user_post_sortby_type']) ? $user_row['user_post_sortby_type'] : 't'), + 'post_sd' => request_var('post_sd', ($user_row['user_post_sortby_dir']) ? $user_row['user_post_sortby_dir'] : 'a'), + 'post_st' => request_var('post_st', ($user_row['user_post_show_days']) ? $user_row['user_post_show_days'] : 0), + + 'view_images' => request_var('view_images', $this->optionget($user_row, 'viewimg')), + 'view_flash' => request_var('view_flash', $this->optionget($user_row, 'viewflash')), + 'view_smilies' => request_var('view_smilies', $this->optionget($user_row, 'viewsmilies')), + 'view_sigs' => request_var('view_sigs', $this->optionget($user_row, 'viewsigs')), + 'view_avatars' => request_var('view_avatars', $this->optionget($user_row, 'viewavatars')), + 'view_wordcensor' => request_var('view_wordcensor', $this->optionget($user_row, 'viewcensors')), + + 'bbcode' => request_var('bbcode', $this->optionget($user_row, 'bbcode')), + 'smilies' => request_var('smilies', $this->optionget($user_row, 'smilies')), + 'sig' => request_var('sig', $this->optionget($user_row, 'attachsig')), + 'notify' => request_var('notify', $user_row['user_notify']), + ); + + if ($submit) + { + $error = validate_data($data, array( + 'dateformat' => array('string', false, 1, 30), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), + 'tz' => array('num', false, -14, 14), + + 'topic_sk' => array('string', false, 1, 1), + 'topic_sd' => array('string', false, 1, 1), + 'post_sk' => array('string', false, 1, 1), + 'post_sd' => array('string', false, 1, 1), + )); + + if (!check_form_key($form_name)) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $this->optionset($user_row, 'popuppm', $data['popuppm']); + $this->optionset($user_row, 'viewimg', $data['view_images']); + $this->optionset($user_row, 'viewflash', $data['view_flash']); + $this->optionset($user_row, 'viewsmilies', $data['view_smilies']); + $this->optionset($user_row, 'viewsigs', $data['view_sigs']); + $this->optionset($user_row, 'viewavatars', $data['view_avatars']); + $this->optionset($user_row, 'viewcensors', $data['view_wordcensor']); + $this->optionset($user_row, 'bbcode', $data['bbcode']); + $this->optionset($user_row, 'smilies', $data['smilies']); + $this->optionset($user_row, 'attachsig', $data['sig']); + + $sql_ary = array( + 'user_options' => $user_row['user_options'], + + 'user_allow_pm' => $data['allowpm'], + 'user_allow_viewemail' => $data['viewemail'], + 'user_allow_massemail' => $data['massemail'], + 'user_allow_viewonline' => !$data['hideonline'], + 'user_notify_type' => $data['notifymethod'], + 'user_notify_pm' => $data['notifypm'], + + 'user_dst' => $data['dst'], + 'user_dateformat' => $data['dateformat'], + 'user_lang' => $data['lang'], + 'user_timezone' => $data['tz'], + 'user_style' => $data['style'], + + 'user_topic_sortby_type' => $data['topic_sk'], + 'user_post_sortby_type' => $data['post_sk'], + 'user_topic_sortby_dir' => $data['topic_sd'], + 'user_post_sortby_dir' => $data['post_sd'], + + 'user_topic_show_days' => $data['topic_st'], + 'user_post_show_days' => $data['post_st'], + + 'user_notify' => $data['notify'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . " + WHERE user_id = $user_id"; + $db->sql_query($sql); + + trigger_error($user->lang['USER_PREFS_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $dateformat_options = ''; + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $data['dateformat']) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $s_custom = false; + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$data['dateformat']])) + { + $dateformat_options .= ' selected="selected"'; + $s_custom = true; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + // Topic ordering options + $limit_topic_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_topic_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); + + // Post ordering options + $limit_post_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_post_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + + $_options = array('topic', 'post'); + foreach ($_options as $sort_option) + { + ${'s_limit_' . $sort_option . '_days'} = '<select name="' . $sort_option . '_st">'; + foreach (${'limit_' . $sort_option . '_days'} as $day => $text) + { + $selected = ($data[$sort_option . '_st'] == $day) ? ' selected="selected"' : ''; + ${'s_limit_' . $sort_option . '_days'} .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_limit_' . $sort_option . '_days'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_key'} = '<select name="' . $sort_option . '_sk">'; + foreach (${'sort_by_' . $sort_option . '_text'} as $key => $text) + { + $selected = ($data[$sort_option . '_sk'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_key'} .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_sort_' . $sort_option . '_key'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_dir'} = '<select name="' . $sort_option . '_sd">'; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($data[$sort_option . '_sd'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_dir'} .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; + } + + $template->assign_vars(array( + 'S_PREFS' => true, + 'S_JABBER_DISABLED' => ($config['jab_enable'] && $user_row['user_jabber'] && @extension_loaded('xml')) ? false : true, + + 'VIEW_EMAIL' => $data['viewemail'], + 'MASS_EMAIL' => $data['massemail'], + 'ALLOW_PM' => $data['allowpm'], + 'HIDE_ONLINE' => $data['hideonline'], + 'NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, + 'NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, + 'NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'NOTIFY_PM' => $data['notifypm'], + 'POPUP_PM' => $data['popuppm'], + 'DST' => $data['dst'], + 'BBCODE' => $data['bbcode'], + 'SMILIES' => $data['smilies'], + 'ATTACH_SIG' => $data['sig'], + 'NOTIFY' => $data['notify'], + 'VIEW_IMAGES' => $data['view_images'], + 'VIEW_FLASH' => $data['view_flash'], + 'VIEW_SMILIES' => $data['view_smilies'], + 'VIEW_SIGS' => $data['view_sigs'], + 'VIEW_AVATARS' => $data['view_avatars'], + 'VIEW_WORDCENSOR' => $data['view_wordcensor'], + + 'S_TOPIC_SORT_DAYS' => $s_limit_topic_days, + 'S_TOPIC_SORT_KEY' => $s_sort_topic_key, + 'S_TOPIC_SORT_DIR' => $s_sort_topic_dir, + 'S_POST_SORT_DAYS' => $s_limit_post_days, + 'S_POST_SORT_KEY' => $s_sort_post_key, + 'S_POST_SORT_DIR' => $s_sort_post_dir, + + 'DATE_FORMAT' => $data['dateformat'], + 'S_DATEFORMAT_OPTIONS' => $dateformat_options, + 'S_CUSTOM_DATEFORMAT' => $s_custom, + 'DEFAULT_DATEFORMAT' => $config['default_dateformat'], + 'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_STYLE_OPTIONS' => style_select($data['style']), + 'S_TZ_OPTIONS' => tz_select($data['tz'], true), + ) + ); + + break; + + case 'avatar': + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $can_upload = (file_exists(PHPBB_ROOT_PATH . $config['avatar_path']) && @is_writable(PHPBB_ROOT_PATH . $config['avatar_path']) && $file_uploads) ? true : false; + + if ($submit) + { + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (avatar_process_user($error, $user_row)) + { + trigger_error($user->lang['USER_AVATAR_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_row['user_id'])); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + // Generate users avatar + $avatar_img = ($user_row['user_avatar']) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']) : '<img src="' . PHPBB_ADMIN_PATH . 'images/no_avatar.gif" alt="" />'; + + $display_gallery = request::is_set_post('display_gallery'); + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + if ($config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $template->assign_vars(array( + 'S_AVATAR' => true, + 'S_CAN_UPLOAD' => ($can_upload && $config['allow_avatar_upload']) ? true : false, + 'S_ALLOW_REMOTE' => ($config['allow_avatar_remote']) ? true : false, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, + + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + 'USER_AVATAR_WIDTH' => $user_row['user_avatar_width'], + 'USER_AVATAR_HEIGHT' => $user_row['user_avatar_height'], + + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], round($config['avatar_filesize'] / 1024))) + ); + + break; + + case 'rank': + + if ($submit) + { + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $rank_id = request_var('user_rank', 0); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_rank = $rank_id + WHERE user_id = $user_id"; + $db->sql_query($sql); + + trigger_error($user->lang['USER_RANK_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $s_rank_options = '<option value="0"' . ((!$user_row['user_rank']) ? ' selected="selected"' : '') . '>' . $user->lang['NO_SPECIAL_RANK'] . '</option>'; + + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($user_row['user_rank'] && $row['rank_id'] == $user_row['user_rank']) ? ' selected="selected"' : ''; + $s_rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_RANK' => true, + 'S_RANK_OPTIONS' => $s_rank_options) + ); + + break; + + case 'sig': + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', !$user->optionget('bbcode'))) ? false : true) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', !$user->optionget('smilies'))) ? false : true) : false; + $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + $signature = utf8_normalize_nfc(request_var('signature', (string) $user_row['user_sig'], true)); + + $preview = request::is_set_post('preview'); + + if ($submit || $preview) + { + include_once(PHPBB_ROOT_PATH . 'includes/message_parser.' . PHP_EXT); + + $message_parser = new parse_message($signature); + + // Allowing Quote BBCode + $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + + if (sizeof($message_parser->warn_msg)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if (!check_form_key($form_name)) + { + $error = 'FORM_INVALID'; + } + + if (!sizeof($error) && $submit) + { + $sql_ary = array( + 'user_sig' => (string) $message_parser->message, + 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, + 'user_sig_bbcode_bitfield' => (string) $message_parser->bbcode_bitfield + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_id; + $db->sql_query($sql); + + trigger_error($user->lang['USER_SIG_UPDATED'] . adm_back_link($this->u_action . '&u=' . $user_id)); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $signature_preview = ''; + + if ($preview) + { + // Now parse it for displaying + $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + unset($message_parser); + } + + decode_message($signature, $user_row['user_sig_bbcode_uid']); + + $template->assign_vars(array( + 'S_SIGNATURE' => true, + + 'SIGNATURE' => $signature, + 'SIGNATURE_PREVIEW' => $signature_preview, + + 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', + 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', + 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', + + 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>'), + 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + + 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + + 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], + 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], + 'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false, + 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false, + 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) + ); + + // Assigning custom bbcodes + display_custom_bbcodes(); + + break; + + case 'attach': + + $start = request_var('start', 0); + $deletemark = request::is_set_post('delmarked'); + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_key = request_var('sk', 'a'); + $sort_dir = request_var('sd', 'd'); + + if ($deletemark && sizeof($marked)) + { + $sql = 'SELECT attach_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user_id . ' + AND is_orphan = 0 + AND ' . $db->sql_in_set('attach_id', $marked); + $result = $db->sql_query($sql); + + $marked = array(); + while ($row = $db->sql_fetchrow($result)) + { + $marked[] = $row['attach_id']; + } + $db->sql_freeresult($result); + } + + if ($deletemark && sizeof($marked)) + { + if (confirm_box(true)) + { + $sql = 'SELECT real_filename + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('attach_id', $marked); + $result = $db->sql_query($sql); + + $log_attachments = array(); + while ($row = $db->sql_fetchrow($result)) + { + $log_attachments[] = $row['real_filename']; + } + $db->sql_freeresult($result); + + delete_attachments('attach', $marked); + + $message = (sizeof($log_attachments) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']; + + add_log('admin', 'LOG_ATTACHMENTS_DELETED', implode(', ', $log_attachments)); + trigger_error($message . adm_back_link($this->u_action . '&u=' . $user_id)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'delmarked' => true, + 'mark' => $marked)) + ); + } + } + + $sk_text = array('a' => $user->lang['SORT_FILENAME'], 'c' => $user->lang['SORT_EXTENSION'], 'd' => $user->lang['SORT_SIZE'], 'e' => $user->lang['SORT_DOWNLOADS'], 'f' => $user->lang['SORT_POST_TIME'], 'g' => $user->lang['SORT_TOPIC_TITLE']); + $sk_sql = array('a' => 'a.real_filename', 'c' => 'a.extension', 'd' => 'a.filesize', 'e' => 'a.download_count', 'f' => 'a.filetime', 'g' => 't.topic_title'); + + $sd_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + $s_sort_key = ''; + foreach ($sk_text as $key => $value) + { + $selected = ($sort_key == $key) ? ' selected="selected"' : ''; + $s_sort_key .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $s_sort_dir = ''; + foreach ($sd_text as $key => $value) + { + $selected = ($sort_dir == $key) ? ' selected="selected"' : ''; + $s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + if (!isset($sk_sql[$sort_key])) + { + $sort_key = 'a'; + } + + $order_by = $sk_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'); + + $sql = 'SELECT COUNT(attach_id) as num_attachments + FROM ' . ATTACHMENTS_TABLE . " + WHERE poster_id = $user_id + AND is_orphan = 0"; + $result = $db->sql_query_limit($sql, 1); + $num_attachments = (int) $db->sql_fetchfield('num_attachments'); + $db->sql_freeresult($result); + + $sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title + FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id + AND a.in_message = 0) + LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id + AND a.in_message = 1) + WHERE a.poster_id = ' . $user_id . " + AND a.is_orphan = 0 + ORDER BY $order_by"; + $result = $db->sql_query_limit($sql, $config['posts_per_page'], $start); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['in_message']) + { + $view_topic = append_sid('ucp', "i=pm&p={$row['post_msg_id']}"); + } + else + { + $view_topic = append_sid('viewtopic', "t={$row['topic_id']}&p={$row['post_msg_id']}") . '#p' . $row['post_msg_id']; + } + + $template->assign_block_vars('attach', array( + 'REAL_FILENAME' => $row['real_filename'], + 'COMMENT' => nl2br($row['attach_comment']), + 'EXTENSION' => $row['extension'], + 'SIZE' => get_formatted_filesize($row['filesize']), + 'DOWNLOAD_COUNT' => $row['download_count'], + 'POST_TIME' => $user->format_date($row['filetime']), + 'TOPIC_TITLE' => ($row['in_message']) ? $row['message_title'] : $row['topic_title'], + + 'ATTACH_ID' => $row['attach_id'], + 'POST_ID' => $row['post_msg_id'], + 'TOPIC_ID' => $row['topic_id'], + + 'S_IN_MESSAGE' => $row['in_message'], + + 'U_DOWNLOAD' => append_sid('download/file', 'mode=view&id=' . $row['attach_id']), + 'U_VIEW_TOPIC' => $view_topic) + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_ATTACHMENTS' => true, + 'S_ON_PAGE' => on_page($num_attachments, $config['topics_per_page'], $start), + 'S_SORT_KEY' => $s_sort_key, + 'S_SORT_DIR' => $s_sort_dir, + + 'PAGINATION' => generate_pagination($this->u_action . "&u=$user_id&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start, true)) + ); + + break; + + case 'groups': + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $user->add_lang(array('groups', 'acp/groups')); + $group_id = request_var('g', 0); + + if ($group_id) + { + // Check the founder only entry for this group to make sure everything is well + $sql = 'SELECT group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_id; + $result = $db->sql_query($sql); + $founder_manage = (int) $db->sql_fetchfield('group_founder_manage'); + $db->sql_freeresult($result); + + if ($user->data['user_type'] != USER_FOUNDER && $founder_manage) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + } + else + { + $founder_manage = 0; + } + + switch ($action) + { + case 'demote': + case 'promote': + case 'default': + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + group_user_attributes($action, $group_id, $user_id); + + if ($action == 'default') + { + $user_row['group_id'] = $group_id; + } + break; + + case 'delete': + + if (confirm_box(true)) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if ($error = group_user_del($group_id, $user_id)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $error = array(); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'u' => $user_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action, + 'g' => $group_id)) + ); + } + + break; + } + + // Add user to group? + if ($submit) + { + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + // Add user/s to group + if ($error = group_user_add($group_id, $user_id)) + { + trigger_error($user->lang[$error] . adm_back_link($this->u_action . '&u=' . $user_id), E_USER_WARNING); + } + + $error = array(); + } + + + $sql = 'SELECT ug.*, g.* + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . " ug + WHERE ug.user_id = $user_id + AND g.group_id = ug.group_id + ORDER BY g.group_type DESC, ug.user_pending ASC, g.group_name"; + $result = $db->sql_query($sql); + + $i = 0; + $group_data = $id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $type = ($row['group_type'] == GROUP_SPECIAL) ? 'special' : (($row['user_pending']) ? 'pending' : 'normal'); + + $group_data[$type][$i]['group_id'] = $row['group_id']; + $group_data[$type][$i]['group_name'] = $row['group_name']; + $group_data[$type][$i]['group_leader'] = ($row['group_leader']) ? 1 : 0; + + $id_ary[] = $row['group_id']; + + $i++; + } + $db->sql_freeresult($result); + + // Select box for other groups + $sql = 'SELECT group_id, group_name, group_type, group_founder_manage + FROM ' . GROUPS_TABLE . ' + ' . ((sizeof($id_ary)) ? 'WHERE ' . $db->sql_in_set('group_id', $id_ary, true) : '') . ' + ORDER BY group_type DESC, group_name ASC'; + $result = $db->sql_query($sql); + + $s_group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + if (!$config['coppa_enable'] && $row['group_name'] == 'REGISTERED_COPPA') + { + continue; + } + + // Do not display those groups not allowed to be managed + if ($user->data['user_type'] != USER_FOUNDER && $row['group_founder_manage']) + { + continue; + } + + $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + + $current_type = ''; + foreach ($group_data as $group_type => $data_ary) + { + if ($current_type != $group_type) + { + $template->assign_block_vars('group', array( + 'S_NEW_GROUP_TYPE' => true, + 'GROUP_TYPE' => $user->lang['USER_GROUP_' . strtoupper($group_type)]) + ); + } + + foreach ($data_ary as $data) + { + $template->assign_block_vars('group', array( + 'U_EDIT_GROUP' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=groups&mode=manage&action=edit&u=$user_id&g={$data['group_id']}&back_link=acp_users_groups"), + 'U_DEFAULT' => $this->u_action . "&action=default&u=$user_id&g=" . $data['group_id'], + 'U_DEMOTE_PROMOTE' => $this->u_action . '&action=' . (($data['group_leader']) ? 'demote' : 'promote') . "&u=$user_id&g=" . $data['group_id'], + 'U_DELETE' => $this->u_action . "&action=delete&u=$user_id&g=" . $data['group_id'], + + 'GROUP_NAME' => ($group_type == 'special') ? $user->lang['G_' . $data['group_name']] : $data['group_name'], + 'L_DEMOTE_PROMOTE' => ($data['group_leader']) ? $user->lang['GROUP_DEMOTE'] : $user->lang['GROUP_PROMOTE'], + + 'S_NO_DEFAULT' => ($user_row['group_id'] != $data['group_id']) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == 'special') ? true : false, + ) + ); + } + } + + $template->assign_vars(array( + 'S_GROUPS' => true, + 'S_GROUP_OPTIONS' => $s_group_options) + ); + + break; + + case 'perm': + + include_once(PHPBB_ROOT_PATH . 'includes/acp/auth.' . PHP_EXT); + + $auth_admin = new auth_admin(); + + $user->add_lang('acp/permissions'); + add_permission_language(); + + $forum_id = request_var('f', 0); + + // Global Permissions + if (!$forum_id) + { + // Select auth options + $sql = 'SELECT auth_option, is_local, is_global + FROM ' . ACL_OPTIONS_TABLE . ' + WHERE auth_option ' . $db->sql_like_expression($db->any_char . '_') . ' + AND is_global = 1 + ORDER BY auth_option'; + $result = $db->sql_query($sql); + + $hold_ary = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary = $auth_admin->get_mask('view', $user_id, false, false, $row['auth_option'], 'global', ACL_NEVER); + $auth_admin->display_mask('view', $row['auth_option'], $hold_ary, 'user', false, false); + } + $db->sql_freeresult($result); + + unset($hold_ary); + } + else + { + $sql = 'SELECT auth_option, is_local, is_global + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($db->any_char . '_') . " + AND is_local = 1 + ORDER BY is_global DESC, auth_option"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary = $auth_admin->get_mask('view', $user_id, false, $forum_id, $row['auth_option'], 'local', ACL_NEVER); + $auth_admin->display_mask('view', $row['auth_option'], $hold_ary, 'user', true, false); + } + $db->sql_freeresult($result); + } + + $s_forum_options = '<option value="0"' . ((!$forum_id) ? ' selected="selected"' : '') . '>' . $user->lang['VIEW_GLOBAL_PERMS'] . '</option>'; + $s_forum_options .= make_forum_select($forum_id, false, true, false, false, false); + + $template->assign_vars(array( + 'S_PERMISSIONS' => true, + + 'S_GLOBAL' => (!$forum_id) ? true : false, + 'S_FORUM_OPTIONS' => $s_forum_options, + + 'U_ACTION' => $this->u_action . '&u=' . $user_id, + 'U_USER_PERMISSIONS' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=permissions&mode=setting_user_global&user_id[]=' . $user_id), + 'U_USER_FORUM_PERMISSIONS' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=permissions&mode=setting_user_local&user_id[]=' . $user_id)) + ); + + break; + + } + + // Assign general variables + $template->assign_vars(array( + 'S_ERROR' => (sizeof($error)) ? true : false, + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '') + ); + } + + /** + * Optionset replacement for this module based on $user->optionset + */ + function optionset(&$user_row, $key, $value, $data = false) + { + global $user; + + $var = ($data) ? $data : $user_row['user_options']; + + if ($value && !($var & 1 << $user->keyoptions[$key])) + { + $var += 1 << $user->keyoptions[$key]; + } + else if (!$value && ($var & 1 << $user->keyoptions[$key])) + { + $var -= 1 << $user->keyoptions[$key]; + } + else + { + return ($data) ? $var : false; + } + + if (!$data) + { + $user_row['user_options'] = $var; + return true; + } + else + { + return $var; + } + } + + /** + * Optionget replacement for this module based on $user->optionget + */ + function optionget(&$user_row, $key, $data = false) + { + global $user; + + $var = ($data) ? $data : $user_row['user_options']; + return ($var & 1 << $user->keyoptions[$key]) ? true : false; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/acp_words.php b/phpBB/modules/acp/acp_words.php new file mode 100644 index 0000000000..1b3d78acaf --- /dev/null +++ b/phpBB/modules/acp/acp_words.php @@ -0,0 +1,184 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @todo [words] check regular expressions for special char replacements (stored specialchared in db) +* @package acp +*/ +class acp_words +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $cache, $config; + + $user->add_lang('acp/posting'); + + // Set up general vars + $action = request_var('action', ''); + $action = (request::is_set_post('add')) ? 'add' : ((request::is_set_post('save')) ? 'save' : $action); + + $s_hidden_fields = ''; + $word_info = array(); + + $this->tpl_name = 'acp_words'; + $this->page_title = 'ACP_WORDS'; + + $form_name = 'acp_words'; + add_form_key($form_name); + + switch ($action) + { + case 'edit': + $word_id = request_var('id', 0); + + if (!$word_id) + { + trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql = 'SELECT * + FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $result = $db->sql_query($sql); + $word_info = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $s_hidden_fields .= '<input type="hidden" name="id" value="' . $word_id . '" />'; + + case 'add': + + $template->assign_vars(array( + 'S_EDIT_WORD' => true, + 'U_ACTION' => $this->u_action, + 'U_BACK' => $this->u_action, + 'WORD' => (isset($word_info['word'])) ? $word_info['word'] : '', + 'REPLACEMENT' => (isset($word_info['replacement'])) ? $word_info['replacement'] : '', + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + return; + + break; + + case 'save': + + if (!check_form_key($form_name)) + { + trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); + } + $word_id = request_var('id', 0); + $word = utf8_normalize_nfc(request_var('word', '', true)); + $replacement = utf8_normalize_nfc(request_var('replacement', '', true)); + + if (!$word || !$replacement) + { + trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + $sql_ary = array( + 'word' => $word, + 'replacement' => $replacement + ); + + if ($word_id) + { + $db->sql_query('UPDATE ' . WORDS_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' WHERE word_id = ' . $word_id); + } + else + { + $db->sql_query('INSERT INTO ' . WORDS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + + $cache->destroy('_word_censors'); + + $log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD'; + add_log('admin', $log_action, $word); + + $message = ($word_id) ? $user->lang['WORD_UPDATED'] : $user->lang['WORD_ADDED']; + trigger_error($message . adm_back_link($this->u_action)); + + break; + + case 'delete': + + $word_id = request_var('id', 0); + + if (!$word_id) + { + trigger_error($user->lang['NO_WORD'] . adm_back_link($this->u_action), E_USER_WARNING); + } + + if (confirm_box(true)) + { + $sql = 'SELECT word + FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $result = $db->sql_query($sql); + $deleted_word = $db->sql_fetchfield('word'); + $db->sql_freeresult($result); + + $sql = 'DELETE FROM ' . WORDS_TABLE . " + WHERE word_id = $word_id"; + $db->sql_query($sql); + + $cache->destroy('_word_censors'); + + add_log('admin', 'LOG_WORD_DELETE', $deleted_word); + + trigger_error($user->lang['WORD_REMOVED'] . adm_back_link($this->u_action)); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'id' => $word_id, + 'action' => 'delete', + ))); + } + + break; + } + + + $template->assign_vars(array( + 'U_ACTION' => $this->u_action, + 'S_HIDDEN_FIELDS' => $s_hidden_fields) + ); + + $sql = 'SELECT * + FROM ' . WORDS_TABLE . ' + ORDER BY word'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('words', array( + 'WORD' => $row['word'], + 'REPLACEMENT' => $row['replacement'], + 'U_EDIT' => $this->u_action . '&action=edit&id=' . $row['word_id'], + 'U_DELETE' => $this->u_action . '&action=delete&id=' . $row['word_id']) + ); + } + $db->sql_freeresult($result); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/auth.php b/phpBB/modules/acp/auth.php new file mode 100644 index 0000000000..0fd78981a9 --- /dev/null +++ b/phpBB/modules/acp/auth.php @@ -0,0 +1,1260 @@ +<?php +/** +* +* @package phpBB3 +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ACP Permission/Auth class +* @package phpBB3 +*/ +class auth_admin extends auth +{ + /** + * Init auth settings + */ + function __construct() + { + global $db, $cache; + + if (($this->acl_options = $cache->get('_acl_options')) === false) + { + $sql = 'SELECT auth_option_id, auth_option, is_global, is_local + FROM ' . ACL_OPTIONS_TABLE . ' + ORDER BY auth_option_id'; + $result = $db->sql_query($sql); + + $global = $local = 0; + $this->acl_options = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['is_global']) + { + $this->acl_options['global'][$row['auth_option']] = $global++; + } + + if ($row['is_local']) + { + $this->acl_options['local'][$row['auth_option']] = $local++; + } + + $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id']; + $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option']; + } + $db->sql_freeresult($result); + + $cache->put('_acl_options', $this->acl_options); + } + } + + /** + * Get permission mask + * This function only supports getting permissions of one type (for example a_) + * + * @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 + * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least) + * @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) + * @param mixed $forum_id forum_ids to search for. Defining a forum id also means getting local settings + * @param string $auth_option the auth_option defines the permission setting to look for (a_ for example) + * @param local|global $scope the scope defines the permission scope. If local, a forum_id is additionally required + * @param ACL_NEVER|ACL_NO|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with + */ + public function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NEVER) + { + global $db, $user; + + $hold_ary = array(); + $view_user_mask = ($mode == 'view' && $group_id === false) ? true : false; + + if ($auth_option === false || $scope === false) + { + return array(); + } + + $acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data'; + + if (!$view_user_mask) + { + if ($forum_id !== false) + { + $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); + } + else + { + $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); + } + } + + // Make sure hold_ary is filled with every setting (prevents missing forums/users/groups) + $ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id); + $forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array()); + + // Only those options we need + $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array('')); + + // If forum_ids is false and the scope is local we actually want to have all forums within the array + if ($scope == 'local' && !sizeof($forum_ids)) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE; + $result = $db->sql_query($sql, 120); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_ids[] = (int) $row['forum_id']; + } + $db->sql_freeresult($result); + } + + if ($view_user_mask) + { + $auth2 = null; + + $sql = 'SELECT user_id, user_permissions, user_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $ug_id); + $result = $db->sql_query($sql); + + while ($userdata = $db->sql_fetchrow($result)) + { + if ($user->data['user_id'] != $userdata['user_id']) + { + $auth2 = new auth(); + $auth2->acl($userdata); + } + else + { + global $auth; + $auth2 = &$auth; + } + + + $hold_ary[$userdata['user_id']] = array(); + foreach ($forum_ids as $f_id) + { + $hold_ary[$userdata['user_id']][$f_id] = array(); + foreach ($compare_options as $option) + { + $hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id); + } + } + } + $db->sql_freeresult($result); + + unset($userdata); + unset($auth2); + } + + foreach ($ug_id as $_id) + { + if (!isset($hold_ary[$_id])) + { + $hold_ary[$_id] = array(); + } + + foreach ($forum_ids as $f_id) + { + if (!isset($hold_ary[$_id][$f_id])) + { + $hold_ary[$_id][$f_id] = array(); + } + } + } + + // Now, we need to fill the gaps with $acl_fill. ;) + + // Now switch back to keys + if (sizeof($compare_options)) + { + $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill)); + } + + // Defining the user-function here to save some memory + $return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';'); + + // Actually fill the gaps + if (sizeof($hold_ary)) + { + foreach ($hold_ary as $ug_id => $row) + { + foreach ($row as $id => $options) + { + // Do not include the global auth_option + unset($options[$auth_option]); + + // Not a "fine" solution, but at all it's a 1-dimensional + // array_diff_key function filling the resulting array values with zeros + // The differences get merged into $hold_ary (all permissions having $acl_fill set) + $hold_ary[$ug_id][$id] = array_merge($options, + + array_map($return_acl_fill, + array_flip( + array_diff( + array_keys($compare_options), array_keys($options) + ) + ) + ) + ); + } + } + } + else + { + $hold_ary[($group_id !== false) ? $group_id : $user_id][(int) $forum_id] = $compare_options; + } + + return $hold_ary; + } + + /** + * Get permission mask for roles + * This function only supports getting masks for one role + */ + public function get_role_mask($role_id) + { + global $db; + + $hold_ary = array(); + + // Get users having this role set... + $sql = 'SELECT user_id, forum_id + FROM ' . ACL_USERS_TABLE . ' + WHERE auth_role_id = ' . $role_id . ' + ORDER BY forum_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['forum_id']]['users'][] = $row['user_id']; + } + $db->sql_freeresult($result); + + // Now grab groups... + $sql = 'SELECT group_id, forum_id + FROM ' . ACL_GROUPS_TABLE . ' + WHERE auth_role_id = ' . $role_id . ' + ORDER BY forum_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hold_ary[$row['forum_id']]['groups'][] = $row['group_id']; + } + $db->sql_freeresult($result); + + return $hold_ary; + } + + /** + * Display permission mask (assign to template) + */ + public function display_mask($mode, $permission_type, array $hold_ary, $user_mode = 'user', $local = false, $group_display = true) + { + global $template, $user, $db; + + // Define names for template loops, might be able to be set + $tpl_pmask = 'p_mask'; + $tpl_fmask = 'f_mask'; + $tpl_category = 'category'; + $tpl_mask = 'mask'; + + $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); + + // Allow trace for viewing permissions and in user mode + $show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false; + + // Get names + if ($user_mode == 'user') + { + $sql = 'SELECT user_id as ug_id, username as ug_name + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . ' + ORDER BY username_clean ASC'; + } + else + { + $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . ' + ORDER BY group_type DESC, group_name ASC'; + } + $result = $db->sql_query($sql); + + $ug_names_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $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']); + } + $db->sql_freeresult($result); + + // Get used forums + $forum_ids = array(); + foreach ($hold_ary as $ug_id => $row) + { + $forum_ids = array_merge($forum_ids, array_keys($row)); + } + $forum_ids = array_unique($forum_ids); + + $forum_names_ary = array(); + if ($local) + { + $forum_names_ary = make_forum_select(false, false, true, false, false, false, true); + + // Remove the disabled ones, since we do not create an option field here... + foreach ($forum_names_ary as $key => $value) + { + if (!$value['disabled']) + { + continue; + } + unset($forum_names_ary[$key]); + } + } + else + { + $forum_names_ary[0] = $l_acl_type; + } + + // Get available roles + $sql = 'SELECT * + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($permission_type) . "' + ORDER BY role_order ASC"; + $result = $db->sql_query($sql); + + $roles = array(); + while ($row = $db->sql_fetchrow($result)) + { + $roles[$row['role_id']] = $row; + } + $db->sql_freeresult($result); + + $cur_roles = $this->acl_role_data($user_mode, $permission_type, array_keys($hold_ary)); + + // Build js roles array (role data assignments) + $s_role_js_array = ''; + + if (sizeof($roles)) + { + $s_role_js_array = array(); + + // Make sure every role (even if empty) has its array defined + foreach ($roles as $_role_id => $null) + { + $s_role_js_array[$_role_id] = "\n" . 'role_options[' . $_role_id . '] = new Array();' . "\n"; + } + + $sql = 'SELECT r.role_id, o.auth_option, r.auth_setting + FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o + WHERE o.auth_option_id = r.auth_option_id + AND ' . $db->sql_in_set('r.role_id', array_keys($roles)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1); + if ($flag == $row['auth_option']) + { + continue; + } + + $s_role_js_array[$row['role_id']] .= 'role_options[' . $row['role_id'] . '][\'' . addslashes($row['auth_option']) . '\'] = ' . $row['auth_setting'] . '; '; + } + $db->sql_freeresult($result); + + $s_role_js_array = implode('', $s_role_js_array); + } + + $template->assign_var('S_ROLE_JS_ARRAY', $s_role_js_array); + unset($s_role_js_array); + + // Now obtain memberships + $user_groups_default = $user_groups_custom = array(); + if ($user_mode == 'user' && $group_display) + { + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . ' + ORDER BY group_type DESC, group_name ASC'; + $result = $db->sql_query($sql); + + $groups = array(); + while ($row = $db->sql_fetchrow($result)) + { + $groups[$row['group_id']] = $row; + } + $db->sql_freeresult($result); + + $memberships = group_memberships(false, array_keys($hold_ary), false); + + // User is not a member of any group? Bad admin, bad bad admin... + if ($memberships) + { + foreach ($memberships as $row) + { + if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL) + { + $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']]; + } + else + { + $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name']; + } + } + } + unset($memberships, $groups); + } + + // If we only have one forum id to display or being in local mode and more than one user/group to display, + // we switch the complete interface to group by user/usergroup instead of grouping by forum + // To achieve this, we need to switch the array a bit + if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1)) + { + $hold_ary_temp = $hold_ary; + $hold_ary = array(); + foreach ($hold_ary_temp as $ug_id => $row) + { + foreach ($forum_names_ary as $forum_id => $forum_row) + { + if (isset($row[$forum_id])) + { + $hold_ary[$forum_id][$ug_id] = $row[$forum_id]; + } + } + } + unset($hold_ary_temp); + + foreach ($hold_ary as $forum_id => $forum_array) + { + $content_array = $categories = array(); + self::build_permission_array($hold_ary[$forum_id], $content_array, $categories, array_keys($ug_names_ary)); + + $template->assign_block_vars($tpl_pmask, array( + 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], + 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], + + 'CATEGORIES' => implode('</th><th>', $categories), + + 'L_ACL_TYPE' => $l_acl_type, + + 'S_LOCAL' => ($local) ? true : false, + 'S_GLOBAL' => (!$local) ? true : false, + 'S_NUM_CATS' => sizeof($categories), + 'S_VIEW' => ($mode == 'view') ? true : false, + 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_USER_MODE' => ($user_mode == 'user') ? true : false, + 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) + ); + + @reset($content_array); + while (list($ug_id, $ug_array) = each($content_array)) + { + // Build role dropdown options + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + + $s_role_options = ''; + + @reset($roles); + while (list($role_id, $role_row) = each($roles)) + { + $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + } + + if ($s_role_options) + { + $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; + } + + if (!$current_role_id && $mode != 'view') + { + $s_custom_permissions = false; + + foreach ($ug_array as $key => $value) + { + if ($value['S_NEVER'] || $value['S_YES']) + { + $s_custom_permissions = true; + break; + } + } + } + else + { + $s_custom_permissions = false; + } + + $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( + 'NAME' => $ug_names_ary[$ug_id], + 'S_ROLE_OPTIONS' => $s_role_options, + 'UG_ID' => $ug_id, + 'S_CUSTOM' => $s_custom_permissions, + 'FORUM_ID' => $forum_id) + ); + + self::assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); + + unset($content_array[$ug_id]); + } + + unset($hold_ary[$forum_id]); + } + } + else + { + foreach ($ug_names_ary as $ug_id => $ug_name) + { + if (!isset($hold_ary[$ug_id])) + { + continue; + } + + $content_array = $categories = array(); + self::build_permission_array($hold_ary[$ug_id], $content_array, $categories, array_keys($forum_names_ary)); + + $template->assign_block_vars($tpl_pmask, array( + 'NAME' => $ug_name, + 'CATEGORIES' => implode('</th><th>', $categories), + + 'USER_GROUPS_DEFAULT' => ($user_mode == 'user' && isset($user_groups_default[$ug_id]) && sizeof($user_groups_default[$ug_id])) ? implode(', ', $user_groups_default[$ug_id]) : '', + 'USER_GROUPS_CUSTOM' => ($user_mode == 'user' && isset($user_groups_custom[$ug_id]) && sizeof($user_groups_custom[$ug_id])) ? implode(', ', $user_groups_custom[$ug_id]) : '', + 'L_ACL_TYPE' => $l_acl_type, + + 'S_LOCAL' => ($local) ? true : false, + 'S_GLOBAL' => (!$local) ? true : false, + 'S_NUM_CATS' => sizeof($categories), + 'S_VIEW' => ($mode == 'view') ? true : false, + 'S_NUM_OBJECTS' => sizeof($content_array), + 'S_USER_MODE' => ($user_mode == 'user') ? true : false, + 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false) + ); + + @reset($content_array); + while (list($forum_id, $forum_array) = each($content_array)) + { + // Build role dropdown options + $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0; + + $s_role_options = ''; + + @reset($roles); + while (list($role_id, $role_row) = each($roles)) + { + $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']); + $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name']; + + $title = ($role_description) ? ' title="' . $role_description . '"' : ''; + $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>'; + } + + if ($s_role_options) + { + $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; + } + + if (!$current_role_id && $mode != 'view') + { + $s_custom_permissions = false; + + foreach ($forum_array as $key => $value) + { + if ($value['S_NEVER'] || $value['S_YES']) + { + $s_custom_permissions = true; + break; + } + } + } + else + { + $s_custom_permissions = false; + } + + $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array( + 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'], + 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'], + 'S_ROLE_OPTIONS' => $s_role_options, + 'S_CUSTOM' => $s_custom_permissions, + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id) + ); + + self::assign_cat_array($forum_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view')); + } + + unset($hold_ary[$ug_id], $ug_names_ary[$ug_id]); + } + } + } + + /** + * Display permission mask for roles + */ + public function display_role_mask(array $hold_ary) + { + global $db, $template, $user; + + if (!sizeof($hold_ary)) + { + return; + } + + // Get forum names + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', array_keys($hold_ary)) . ' + ORDER BY left_id'; + $result = $db->sql_query($sql); + + // If the role is used globally, then reflect that + $forum_names = (isset($hold_ary[0])) ? array(0 => '') : array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + foreach ($forum_names as $forum_id => $forum_name) + { + $auth_ary = $hold_ary[$forum_id]; + + $template->assign_block_vars('role_mask', array( + 'NAME' => ($forum_id == 0) ? $user->lang['GLOBAL_MASK'] : $forum_name, + 'FORUM_ID' => $forum_id) + ); + + if (isset($auth_ary['users']) && sizeof($auth_ary['users'])) + { + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $auth_ary['users']) . ' + ORDER BY username_clean ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('role_mask.users', array( + 'USER_ID' => $row['user_id'], + 'USERNAME' => $row['username'], + 'U_PROFILE' => append_sid('memberlist', "mode=viewprofile&u={$row['user_id']}")) + ); + } + $db->sql_freeresult($result); + } + + if (isset($auth_ary['groups']) && sizeof($auth_ary['groups'])) + { + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE ' . $db->sql_in_set('group_id', $auth_ary['groups']) . ' + ORDER BY group_type ASC, group_name'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('role_mask.groups', array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'U_PROFILE' => append_sid('memberlist', "mode=group&g={$row['group_id']}")) + ); + } + $db->sql_freeresult($result); + } + } + } + + /** + * NOTE: this function is not in use atm + * Add a new option to the list ... $options is a hash of form -> + * $options = array( + * 'local' => array('option1', 'option2', ...), + * 'global' => array('optionA', 'optionB', ...) + * ); + */ + public function acl_add_option(array $options) + { + global $db, $cache; + + $cur_options = array(); + + $sql = 'SELECT auth_option, is_global, is_local + FROM ' . ACL_OPTIONS_TABLE . ' + ORDER BY auth_option_id'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['is_global']) + { + $cur_options['global'][] = $row['auth_option']; + } + + if ($row['is_local']) + { + $cur_options['local'][] = $row['auth_option']; + } + } + $db->sql_freeresult($result); + + // Here we need to insert new options ... this requires discovering whether + // an options is global, local or both and whether we need to add an permission + // set flag (x_) + $new_options = array('local' => array(), 'global' => array()); + + foreach ($options as $type => $option_ary) + { + $option_ary = array_unique($option_ary); + + foreach ($option_ary as $option_value) + { + if (!in_array($option_value, $cur_options[$type])) + { + $new_options[$type][] = $option_value; + } + + $flag = substr($option_value, 0, strpos($option_value, '_') + 1); + + if (!in_array($flag, $cur_options[$type]) && !in_array($flag, $new_options[$type])) + { + $new_options[$type][] = $flag; + } + } + } + unset($options); + + $options = array(); + $options['local'] = array_diff($new_options['local'], $new_options['global']); + $options['global'] = array_diff($new_options['global'], $new_options['local']); + $options['local_global'] = array_intersect($new_options['local'], $new_options['global']); + + $sql_ary = array(); + + foreach ($options as $type => $option_ary) + { + foreach ($option_ary as $option) + { + $sql_ary[] = array( + 'auth_option' => (string) $option, + 'is_global' => ($type == 'global' || $type == 'local_global') ? 1 : 0, + 'is_local' => ($type == 'local' || $type == 'local_global') ? 1 : 0 + ); + } + } + + $db->sql_multi_insert(ACL_OPTIONS_TABLE, $sql_ary); + + $cache->destroy('_acl_options'); + $this->acl_clear_prefetch(); + + // Because we just changed the options and also purged the options cache, we instantly update/regenerate it for later calls to succeed. + $this->acl_options = array(); + $this->__construct(); + + return true; + } + + /** + * Set a user or group ACL record + */ + public function acl_set($ug_type, $forum_id, $ug_id, $auth, $role_id = 0, $clear_prefetch = true) + { + global $db; + + // One or more forums + if (!is_array($forum_id)) + { + $forum_id = array($forum_id); + } + + // One or more users + if (!is_array($ug_id)) + { + $ug_id = array($ug_id); + } + + $ug_id_sql = $db->sql_in_set($ug_type . '_id', array_map('intval', $ug_id)); + $forum_sql = $db->sql_in_set('forum_id', array_map('intval', $forum_id)); + + // Instead of updating, inserting, removing we just remove all current settings and re-set everything... + $table = ($ug_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE; + $id_field = $ug_type . '_id'; + + // Get any flags as required + reset($auth); + $flag = key($auth); + $flag = substr($flag, 0, strpos($flag, '_') + 1); + + // This ID (the any-flag) is set if one or more permissions are true... + $any_option_id = (int) $this->acl_options['id'][$flag]; + + // Remove any-flag from auth ary + if (isset($auth[$flag])) + { + unset($auth[$flag]); + } + + // Remove current auth options... + $auth_option_ids = array((int)$any_option_id); + foreach ($auth as $auth_option => $auth_setting) + { + $auth_option_ids[] = (int) $this->acl_options['id'][$auth_option]; + } + + $sql = "DELETE FROM $table + WHERE $forum_sql + AND $ug_id_sql + AND " . $db->sql_in_set('auth_option_id', $auth_option_ids); + $db->sql_query($sql); + + // Remove those having a role assigned... the correct type of course... + $sql = 'SELECT role_id + FROM ' . ACL_ROLES_TABLE . " + WHERE role_type = '" . $db->sql_escape($flag) . "'"; + $result = $db->sql_query($sql); + + $role_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $role_ids[] = $row['role_id']; + } + $db->sql_freeresult($result); + + if (sizeof($role_ids)) + { + $sql = "DELETE FROM $table + WHERE $forum_sql + AND $ug_id_sql + AND auth_option_id = 0 + AND " . $db->sql_in_set('auth_role_id', $role_ids); + $db->sql_query($sql); + } + + // Ok, include the any-flag if one or more auth options are set to yes... + foreach ($auth as $auth_option => $setting) + { + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) + { + $auth[$flag] = ACL_YES; + } + } + + $sql_ary = array(); + foreach ($forum_id as $forum) + { + $forum = (int) $forum; + + if ($role_id) + { + foreach ($ug_id as $id) + { + $sql_ary[] = array( + $id_field => (int) $id, + 'forum_id' => (int) $forum, + 'auth_option_id' => 0, + 'auth_setting' => 0, + 'auth_role_id' => (int) $role_id, + ); + } + } + else + { + foreach ($auth as $auth_option => $setting) + { + $auth_option_id = (int) $this->acl_options['id'][$auth_option]; + + if ($setting != ACL_NO) + { + foreach ($ug_id as $id) + { + $sql_ary[] = array( + $id_field => (int) $id, + 'forum_id' => (int) $forum, + 'auth_option_id' => (int) $auth_option_id, + 'auth_setting' => (int) $setting + ); + } + } + } + } + } + + $db->sql_multi_insert($table, $sql_ary); + + if ($clear_prefetch) + { + $this->acl_clear_prefetch(); + } + } + + /** + * Set a role-specific ACL record + */ + public function acl_set_role($role_id, $auth) + { + global $db; + + // Get any-flag as required + reset($auth); + $flag = key($auth); + $flag = substr($flag, 0, strpos($flag, '_') + 1); + + // Remove any-flag from auth ary + if (isset($auth[$flag])) + { + unset($auth[$flag]); + } + + // Re-set any flag... + foreach ($auth as $auth_option => $setting) + { + if ($setting == ACL_YES && (!isset($auth[$flag]) || $auth[$flag] == ACL_NEVER)) + { + $auth[$flag] = ACL_YES; + } + } + + $sql_ary = array(); + foreach ($auth as $auth_option => $setting) + { + $auth_option_id = (int) $this->acl_options['id'][$auth_option]; + + if ($setting != ACL_NO) + { + $sql_ary[] = array( + 'role_id' => (int) $role_id, + 'auth_option_id' => (int) $auth_option_id, + 'auth_setting' => (int) $setting + ); + } + } + + // If no data is there, we set the any-flag to ACL_NEVER... + if (!sizeof($sql_ary)) + { + $sql_ary[] = array( + 'role_id' => (int) $role_id, + 'auth_option_id' => (int) $this->acl_options['id'][$flag], + 'auth_setting' => ACL_NEVER + ); + } + + // Remove current auth options... + $sql = 'DELETE FROM ' . ACL_ROLES_DATA_TABLE . ' + WHERE role_id = ' . $role_id; + $db->sql_query($sql); + + // Now insert the new values + $db->sql_multi_insert(ACL_ROLES_DATA_TABLE, $sql_ary); + + $this->acl_clear_prefetch(); + } + + /** + * Remove local permission + */ + public function acl_delete($mode, $ug_id = false, $forum_id = false, $permission_type = false) + { + global $db; + + if ($ug_id === false && $forum_id === false) + { + return; + } + + $option_id_ary = array(); + $table = ($mode == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE; + $id_field = $mode . '_id'; + + $where_sql = array(); + + if ($forum_id !== false) + { + $where_sql[] = (!is_array($forum_id)) ? 'forum_id = ' . (int) $forum_id : $db->sql_in_set('forum_id', array_map('intval', $forum_id)); + } + + if ($ug_id !== false) + { + $where_sql[] = (!is_array($ug_id)) ? $id_field . ' = ' . (int) $ug_id : $db->sql_in_set($id_field, array_map('intval', $ug_id)); + } + + // There seem to be auth options involved, therefore we need to go through the list and make sure we capture roles correctly + if ($permission_type !== false) + { + // Get permission type + $sql = 'SELECT auth_option, auth_option_id + FROM ' . ACL_OPTIONS_TABLE . " + WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char); + $result = $db->sql_query($sql); + + $auth_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $option_id_ary[] = $row['auth_option_id']; + $auth_id_ary[$row['auth_option']] = ACL_NO; + } + $db->sql_freeresult($result); + + // First of all, lets grab the items having roles with the specified auth options assigned + $sql = "SELECT auth_role_id, $id_field, forum_id + FROM $table, " . ACL_ROLES_TABLE . " r + WHERE auth_role_id <> 0 + AND auth_role_id = r.role_id + AND r.role_type = '{$permission_type}' + AND " . implode(' AND ', $where_sql) . ' + ORDER BY auth_role_id'; + $result = $db->sql_query($sql); + + $cur_role_auth = array(); + while ($row = $db->sql_fetchrow($result)) + { + $cur_role_auth[$row['auth_role_id']][$row['forum_id']][] = $row[$id_field]; + } + $db->sql_freeresult($result); + + // Get role data for resetting data + if (sizeof($cur_role_auth)) + { + $sql = 'SELECT ao.auth_option, rd.role_id, rd.auth_setting + FROM ' . ACL_OPTIONS_TABLE . ' ao, ' . ACL_ROLES_DATA_TABLE . ' rd + WHERE ao.auth_option_id = rd.auth_option_id + AND ' . $db->sql_in_set('rd.role_id', array_keys($cur_role_auth)); + $result = $db->sql_query($sql); + + $auth_settings = array(); + while ($row = $db->sql_fetchrow($result)) + { + // We need to fill all auth_options, else setting it will fail... + if (!isset($auth_settings[$row['role_id']])) + { + $auth_settings[$row['role_id']] = $auth_id_ary; + } + $auth_settings[$row['role_id']][$row['auth_option']] = $row['auth_setting']; + } + $db->sql_freeresult($result); + + // Set the options + foreach ($cur_role_auth as $role_id => $auth_row) + { + foreach ($auth_row as $f_id => $ug_row) + { + $this->acl_set($mode, $f_id, $ug_row, $auth_settings[$role_id], 0, false); + } + } + } + } + + // Now, normally remove permissions... + if ($permission_type !== false) + { + $where_sql[] = $db->sql_in_set('auth_option_id', array_map('intval', $option_id_ary)); + } + + $sql = "DELETE FROM $table + WHERE " . implode(' AND ', $where_sql); + $db->sql_query($sql); + + $this->acl_clear_prefetch(); + } + + /** + * Assign category to template + * used by display_mask() + */ + private static function assign_cat_array(array $category_array, $tpl_cat, $tpl_mask, $ug_id, $forum_id, $show_trace = false, $s_view) + { + global $template, $user; + + @reset($category_array); + while (list($cat, $cat_array) = each($category_array)) + { + $template->assign_block_vars($tpl_cat, array( + 'S_YES' => ($cat_array['S_YES'] && !$cat_array['S_NEVER'] && !$cat_array['S_NO']) ? true : false, + 'S_NEVER' => ($cat_array['S_NEVER'] && !$cat_array['S_YES'] && !$cat_array['S_NO']) ? true : false, + 'S_NO' => ($cat_array['S_NO'] && !$cat_array['S_NEVER'] && !$cat_array['S_YES']) ? true : false, + + 'CAT_NAME' => $user->lang['permission_cat'][$cat]) + ); + + /* Sort permissions by name (more naturaly and user friendly than sorting by a primary key) + * Commented out due to it's memory consumption and time needed + * + $key_array = array_intersect(array_keys($user->lang), array_map(create_function('$a', 'return "acl_" . $a;'), array_keys($cat_array['permissions']))); + $values_array = $cat_array['permissions']; + + $cat_array['permissions'] = array(); + + foreach ($key_array as $key) + { + $key = str_replace('acl_', '', $key); + $cat_array['permissions'][$key] = $values_array[$key]; + } + unset($key_array, $values_array); +*/ + @reset($cat_array['permissions']); + while (list($permission, $allowed) = each($cat_array['permissions'])) + { + if ($s_view) + { + $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id, + 'FIELD_NAME' => $permission, + 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']', + + 'U_TRACE' => ($show_trace) ? append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '', + 'UA_TRACE' => ($show_trace) ? append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', + + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + else + { + $template->assign_block_vars($tpl_cat . '.' . $tpl_mask, array( + 'S_YES' => ($allowed == ACL_YES) ? true : false, + 'S_NEVER' => ($allowed == ACL_NEVER) ? true : false, + 'S_NO' => ($allowed == ACL_NO) ? true : false, + + 'UG_ID' => $ug_id, + 'FORUM_ID' => $forum_id, + 'FIELD_NAME' => $permission, + 'S_FIELD_NAME' => 'setting[' . $ug_id . '][' . $forum_id . '][' . $permission . ']', + + 'U_TRACE' => ($show_trace) ? append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission") : '', + 'UA_TRACE' => ($show_trace) ? append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i=permissions&mode=trace&u=$ug_id&f=$forum_id&auth=$permission", false) : '', + + 'PERMISSION' => $user->lang['acl_' . $permission]['lang']) + ); + } + } + } + } + + /** + * Building content array from permission rows with explicit key ordering + * used by display_mask() + */ + public static function build_permission_array(array $permission_row, array &$content_array, array &$categories, array $key_sort_array) + { + global $user; + + foreach ($key_sort_array as $forum_id) + { + if (!isset($permission_row[$forum_id])) + { + continue; + } + + $permissions = $permission_row[$forum_id]; + ksort($permissions); + + @reset($permissions); + while (list($permission, $auth_setting) = each($permissions)) + { + if (!isset($user->lang['acl_' . $permission])) + { + $user->lang['acl_' . $permission] = array( + 'cat' => 'misc', + 'lang' => '{ acl_' . $permission . ' }' + ); + } + + $cat = $user->lang['acl_' . $permission]['cat']; + + // Build our categories array + if (!isset($categories[$cat])) + { + $categories[$cat] = $user->lang['permission_cat'][$cat]; + } + + // Build our content array + if (!isset($content_array[$forum_id])) + { + $content_array[$forum_id] = array(); + } + + if (!isset($content_array[$forum_id][$cat])) + { + $content_array[$forum_id][$cat] = array( + 'S_YES' => false, + 'S_NEVER' => false, + 'S_NO' => false, + 'permissions' => array(), + ); + } + + $content_array[$forum_id][$cat]['S_YES'] |= ($auth_setting == ACL_YES) ? true : false; + $content_array[$forum_id][$cat]['S_NEVER'] |= ($auth_setting == ACL_NEVER) ? true : false; + $content_array[$forum_id][$cat]['S_NO'] |= ($auth_setting == ACL_NO) ? true : false; + + $content_array[$forum_id][$cat]['permissions'][$permission] = $auth_setting; + } + } + } + + /** + * Use permissions from another user. This transferes a permission set from one user to another. + * The other user is always able to revert back to his permission set. + * This function does not check for lower/higher permissions, it is possible for the user to gain + * "more" permissions by this. + * Admin permissions will not be copied. + */ + public function ghost_permissions($from_user_id, $to_user_id) + { + global $db; + + if ($to_user_id == ANONYMOUS) + { + return false; + } + + $hold_ary = $this->acl_raw_data_single_user($from_user_id); + + // Key 0 in $hold_ary are global options, all others are forum_ids + + // We disallow copying admin permissions + foreach ($this->acl_options['global'] as $opt => $id) + { + if (strpos($opt, 'a_') === 0) + { + $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_NEVER; + } + } + + // Force a_switchperm to be allowed + $hold_ary[0][$this->acl_options['id']['a_switchperm']] = ACL_YES; + + $user_permissions = $this->build_bitstring($hold_ary); + + if (!$user_permissions) + { + return false; + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '" . $db->sql_escape($user_permissions) . "', + user_perm_from = $from_user_id + WHERE user_id = " . $to_user_id; + $db->sql_query($sql); + + return true; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_attachments.php b/phpBB/modules/acp/info/acp_attachments.php new file mode 100644 index 0000000000..b77785801f --- /dev/null +++ b/phpBB/modules/acp/info/acp_attachments.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_attachments_info +{ + function module() + { + return array( + 'filename' => 'acp_attachments', + 'title' => 'ACP_ATTACHMENTS', + 'version' => '1.0.0', + 'modes' => array( + 'attach' => array('title' => 'ACP_ATTACHMENT_SETTINGS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_ATTACHMENTS')), + 'extensions' => array('title' => 'ACP_MANAGE_EXTENSIONS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), + 'ext_groups' => array('title' => 'ACP_EXTENSION_GROUPS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')), + 'orphan' => array('title' => 'ACP_ORPHAN_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')) + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_ban.php b/phpBB/modules/acp/info/acp_ban.php new file mode 100644 index 0000000000..df51011ec6 --- /dev/null +++ b/phpBB/modules/acp/info/acp_ban.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_ban_info +{ + function module() + { + return array( + 'filename' => 'acp_ban', + 'title' => 'ACP_BAN', + 'version' => '1.0.0', + 'modes' => array( + 'email' => array('title' => 'ACP_BAN_EMAILS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + 'ip' => array('title' => 'ACP_BAN_IPS', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + 'user' => array('title' => 'ACP_BAN_USERNAMES', 'auth' => 'acl_a_ban', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_bbcodes.php b/phpBB/modules/acp/info/acp_bbcodes.php new file mode 100644 index 0000000000..c0206432d6 --- /dev/null +++ b/phpBB/modules/acp/info/acp_bbcodes.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_bbcodes_info +{ + function module() + { + return array( + 'filename' => 'acp_bbcodes', + 'title' => 'ACP_BBCODES', + 'version' => '1.0.0', + 'modes' => array( + 'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_board.php b/phpBB/modules/acp/info/acp_board.php new file mode 100644 index 0000000000..72d86676a6 --- /dev/null +++ b/phpBB/modules/acp/info/acp_board.php @@ -0,0 +1,51 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_board_info +{ + function module() + { + return array( + 'filename' => 'acp_board', + 'title' => 'ACP_BOARD_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_BOARD_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'features' => array('title' => 'ACP_BOARD_FEATURES', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'avatar' => array('title' => 'ACP_AVATAR_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'message' => array('title' => 'ACP_MESSAGE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION', 'ACP_MESSAGES')), + 'post' => array('title' => 'ACP_POST_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'signature' => array('title' => 'ACP_SIGNATURE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'registration' => array('title' => 'ACP_REGISTER_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + + 'auth' => array('title' => 'ACP_AUTH_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + 'email' => array('title' => 'ACP_EMAIL_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + + 'cookie' => array('title' => 'ACP_COOKIE_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'server' => array('title' => 'ACP_SERVER_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'security' => array('title' => 'ACP_SECURITY_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'load' => array('title' => 'ACP_LOAD_SETTINGS', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_bots.php b/phpBB/modules/acp/info/acp_bots.php new file mode 100644 index 0000000000..45087f9225 --- /dev/null +++ b/phpBB/modules/acp/info/acp_bots.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_bots_info +{ + function module() + { + return array( + 'filename' => 'acp_bots', + 'title' => 'ACP_BOTS', + 'version' => '1.0.0', + 'modes' => array( + 'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_captcha.php b/phpBB/modules/acp/info/acp_captcha.php new file mode 100644 index 0000000000..b2541c252c --- /dev/null +++ b/phpBB/modules/acp/info/acp_captcha.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_captcha_info +{ + function module() + { + return array( + 'filename' => 'acp_captcha', + 'title' => 'ACP_CAPTCHA', + 'version' => '1.0.0', + 'modes' => array( + 'visual' => array('title' => 'ACP_VC_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')), + 'img' => array('title' => 'ACP_VC_CAPTCHA_DISPLAY', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION'), 'display' => false) + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_database.php b/phpBB/modules/acp/info/acp_database.php new file mode 100644 index 0000000000..85c3c8b21c --- /dev/null +++ b/phpBB/modules/acp/info/acp_database.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_database_info +{ + function module() + { + return array( + 'filename' => 'acp_database', + 'title' => 'ACP_DATABASE', + 'version' => '1.0.0', + 'modes' => array( + 'backup' => array('title' => 'ACP_BACKUP', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), + 'restore' => array('title' => 'ACP_RESTORE', 'auth' => 'acl_a_backup', 'cat' => array('ACP_CAT_DATABASE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_disallow.php b/phpBB/modules/acp/info/acp_disallow.php new file mode 100644 index 0000000000..41315eb716 --- /dev/null +++ b/phpBB/modules/acp/info/acp_disallow.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_disallow_info +{ + function module() + { + return array( + 'filename' => 'acp_disallow', + 'title' => 'ACP_DISALLOW', + 'version' => '1.0.0', + 'modes' => array( + 'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_email.php b/phpBB/modules/acp/info/acp_email.php new file mode 100644 index 0000000000..4ad7bca58b --- /dev/null +++ b/phpBB/modules/acp/info/acp_email.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_email_info +{ + function module() + { + return array( + 'filename' => 'acp_email', + 'title' => 'ACP_MASS_EMAIL', + 'version' => '1.0.0', + 'modes' => array( + 'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_forums.php b/phpBB/modules/acp/info/acp_forums.php new file mode 100644 index 0000000000..8d82eaf42d --- /dev/null +++ b/phpBB/modules/acp/info/acp_forums.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_forums_info +{ + function module() + { + return array( + 'filename' => 'acp_forums', + 'title' => 'ACP_FORUM_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_groups.php b/phpBB/modules/acp/info/acp_groups.php new file mode 100644 index 0000000000..3910c24e6b --- /dev/null +++ b/phpBB/modules/acp/info/acp_groups.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_groups_info +{ + function module() + { + return array( + 'filename' => 'acp_groups', + 'title' => 'ACP_GROUPS_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_icons.php b/phpBB/modules/acp/info/acp_icons.php new file mode 100644 index 0000000000..16bf753940 --- /dev/null +++ b/phpBB/modules/acp/info/acp_icons.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_icons_info +{ + function module() + { + return array( + 'filename' => 'acp_icons', + 'title' => 'ACP_ICONS_SMILIES', + 'version' => '1.0.0', + 'modes' => array( + 'icons' => array('title' => 'ACP_ICONS', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), + 'smilies' => array('title' => 'ACP_SMILIES', 'auth' => 'acl_a_icons', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_inactive.php b/phpBB/modules/acp/info/acp_inactive.php new file mode 100644 index 0000000000..e17fbda9dd --- /dev/null +++ b/phpBB/modules/acp/info/acp_inactive.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2006 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_inactive_info +{ + function module() + { + return array( + 'filename' => 'acp_inactive', + 'title' => 'ACP_INACTIVE_USERS', + 'version' => '1.0.0', + 'modes' => array( + 'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_jabber.php b/phpBB/modules/acp/info/acp_jabber.php new file mode 100644 index 0000000000..7bcf7744e1 --- /dev/null +++ b/phpBB/modules/acp/info/acp_jabber.php @@ -0,0 +1,36 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_jabber_info +{ + function module() + { + return array( + 'filename' => 'acp_jabber', + 'title' => 'ACP_JABBER_SETTINGS', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_language.php b/phpBB/modules/acp/info/acp_language.php new file mode 100644 index 0000000000..f7606631fe --- /dev/null +++ b/phpBB/modules/acp/info/acp_language.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_language_info +{ + function module() + { + return array( + 'filename' => 'acp_language', + 'title' => 'ACP_LANGUAGE', + 'version' => '1.0.0', + 'modes' => array( + 'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_logs.php b/phpBB/modules/acp/info/acp_logs.php new file mode 100644 index 0000000000..f119e10b83 --- /dev/null +++ b/phpBB/modules/acp/info/acp_logs.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_logs_info +{ + function module() + { + return array( + 'filename' => 'acp_logs', + 'title' => 'ACP_LOGGING', + 'version' => '1.0.0', + 'modes' => array( + 'admin' => array('title' => 'ACP_ADMIN_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'mod' => array('title' => 'ACP_MOD_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'users' => array('title' => 'ACP_USERS_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + 'critical' => array('title' => 'ACP_CRITICAL_LOGS', 'auth' => 'acl_a_viewlogs', 'cat' => array('ACP_FORUM_LOGS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_main.php b/phpBB/modules/acp/info/acp_main.php new file mode 100644 index 0000000000..5574cc40d1 --- /dev/null +++ b/phpBB/modules/acp/info/acp_main.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_main_info +{ + function module() + { + return array( + 'filename' => 'acp_main', + 'title' => 'ACP_INDEX', + 'version' => '1.0.0', + 'modes' => array( + 'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_modules.php b/phpBB/modules/acp/info/acp_modules.php new file mode 100644 index 0000000000..886f17d628 --- /dev/null +++ b/phpBB/modules/acp/info/acp_modules.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_modules_info +{ + function module() + { + return array( + 'filename' => 'acp_modules', + 'title' => 'ACP_MODULE_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'acp' => array('title' => 'ACP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + 'ucp' => array('title' => 'UCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + 'mcp' => array('title' => 'MCP', 'auth' => 'acl_a_modules', 'cat' => array('ACP_MODULE_MANAGEMENT')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_permission_roles.php b/phpBB/modules/acp/info/acp_permission_roles.php new file mode 100644 index 0000000000..3ab2fecd53 --- /dev/null +++ b/phpBB/modules/acp/info/acp_permission_roles.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_permission_roles_info +{ + function module() + { + return array( + 'filename' => 'acp_permission_roles', + 'title' => 'ACP_PERMISSION_ROLES', + 'version' => '1.0.0', + 'modes' => array( + 'admin_roles' => array('title' => 'ACP_ADMIN_ROLES', 'auth' => 'acl_a_roles && acl_a_aauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'user_roles' => array('title' => 'ACP_USER_ROLES', 'auth' => 'acl_a_roles && acl_a_uauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'mod_roles' => array('title' => 'ACP_MOD_ROLES', 'auth' => 'acl_a_roles && acl_a_mauth', 'cat' => array('ACP_PERMISSION_ROLES')), + 'forum_roles' => array('title' => 'ACP_FORUM_ROLES', 'auth' => 'acl_a_roles && acl_a_fauth', 'cat' => array('ACP_PERMISSION_ROLES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_permissions.php b/phpBB/modules/acp/info/acp_permissions.php new file mode 100644 index 0000000000..22de666af3 --- /dev/null +++ b/phpBB/modules/acp/info/acp_permissions.php @@ -0,0 +1,53 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_permissions_info +{ + function module() + { + return array( + 'filename' => 'acp_permissions', + 'title' => 'ACP_PERMISSIONS', + 'version' => '1.0.0', + 'modes' => array( + 'intro' => array('title' => 'ACP_PERMISSIONS', 'auth' => 'acl_a_authusers || acl_a_authgroups || acl_a_viewauth', 'cat' => array('ACP_CAT_PERMISSIONS')), + 'trace' => array('title' => 'ACP_PERMISSION_TRACE', 'auth' => 'acl_a_viewauth', 'display' => false, 'cat' => array('ACP_PERMISSION_MASKS')), + + 'setting_forum_local' => array('title' => 'ACP_FORUM_PERMISSIONS', 'auth' => 'acl_a_fauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')), + 'setting_mod_local' => array('title' => 'ACP_FORUM_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS')), + 'setting_user_global' => array('title' => 'ACP_USERS_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_CAT_USERS')), + 'setting_user_local' => array('title' => 'ACP_USERS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authusers && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_CAT_USERS')), + 'setting_group_global' => array('title' => 'ACP_GROUPS_PERMISSIONS', 'auth' => 'acl_a_authgroups && (acl_a_aauth || acl_a_mauth || acl_a_uauth)', 'cat' => array('ACP_GLOBAL_PERMISSIONS', 'ACP_GROUPS')), + 'setting_group_local' => array('title' => 'ACP_GROUPS_FORUM_PERMISSIONS', 'auth' => 'acl_a_authgroups && (acl_a_mauth || acl_a_fauth)', 'cat' => array('ACP_FORUM_BASED_PERMISSIONS', 'ACP_GROUPS')), + 'setting_admin_global' => array('title' => 'ACP_ADMINISTRATORS', 'auth' => 'acl_a_aauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_GLOBAL_PERMISSIONS')), + 'setting_mod_global' => array('title' => 'ACP_GLOBAL_MODERATORS', 'auth' => 'acl_a_mauth && (acl_a_authusers || acl_a_authgroups)', 'cat' => array('ACP_GLOBAL_PERMISSIONS')), + + 'view_admin_global' => array('title' => 'ACP_VIEW_ADMIN_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_user_global' => array('title' => 'ACP_VIEW_USER_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_mod_global' => array('title' => 'ACP_VIEW_GLOBAL_MOD_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_mod_local' => array('title' => 'ACP_VIEW_FORUM_MOD_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + 'view_forum_local' => array('title' => 'ACP_VIEW_FORUM_PERMISSIONS', 'auth' => 'acl_a_viewauth', 'cat' => array('ACP_PERMISSION_MASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_php_info.php b/phpBB/modules/acp/info/acp_php_info.php new file mode 100644 index 0000000000..7d716b0f83 --- /dev/null +++ b/phpBB/modules/acp/info/acp_php_info.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_php_info_info +{ + function module() + { + return array( + 'filename' => 'acp_php_info', + 'title' => 'ACP_PHP_INFO', + 'version' => '1.0.0', + 'modes' => array( + 'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_profile.php b/phpBB/modules/acp/info/acp_profile.php new file mode 100644 index 0000000000..8590226038 --- /dev/null +++ b/phpBB/modules/acp/info/acp_profile.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_profile_info +{ + function module() + { + return array( + 'filename' => 'acp_profile', + 'title' => 'ACP_CUSTOM_PROFILE_FIELDS', + 'version' => '1.0.0', + 'modes' => array( + 'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_prune.php b/phpBB/modules/acp/info/acp_prune.php new file mode 100644 index 0000000000..46565c4f16 --- /dev/null +++ b/phpBB/modules/acp/info/acp_prune.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_prune_info +{ + function module() + { + return array( + 'filename' => 'acp_prune', + 'title' => 'ACP_PRUNING', + 'version' => '1.0.0', + 'modes' => array( + 'forums' => array('title' => 'ACP_PRUNE_FORUMS', 'auth' => 'acl_a_prune', 'cat' => array('ACP_MANAGE_FORUMS')), + 'users' => array('title' => 'ACP_PRUNE_USERS', 'auth' => 'acl_a_userdel', 'cat' => array('ACP_USER_SECURITY')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_ranks.php b/phpBB/modules/acp/info/acp_ranks.php new file mode 100644 index 0000000000..06b9c6d284 --- /dev/null +++ b/phpBB/modules/acp/info/acp_ranks.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_ranks_info +{ + function module() + { + return array( + 'filename' => 'acp_ranks', + 'title' => 'ACP_RANKS', + 'version' => '1.0.0', + 'modes' => array( + 'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_reasons.php b/phpBB/modules/acp/info/acp_reasons.php new file mode 100644 index 0000000000..65d805ee18 --- /dev/null +++ b/phpBB/modules/acp/info/acp_reasons.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_reasons_info +{ + function module() + { + return array( + 'filename' => 'acp_reasons', + 'title' => 'ACP_REASONS', + 'version' => '1.0.0', + 'modes' => array( + 'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_search.php b/phpBB/modules/acp/info/acp_search.php new file mode 100644 index 0000000000..4afd6c6994 --- /dev/null +++ b/phpBB/modules/acp/info/acp_search.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_search_info +{ + function module() + { + return array( + 'filename' => 'acp_search', + 'title' => 'ACP_SEARCH', + 'version' => '1.0.0', + 'modes' => array( + 'settings' => array('title' => 'ACP_SEARCH_SETTINGS', 'auth' => 'acl_a_search', 'cat' => array('ACP_SERVER_CONFIGURATION')), + 'index' => array('title' => 'ACP_SEARCH_INDEX', 'auth' => 'acl_a_search', 'cat' => array('ACP_CAT_DATABASE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_styles.php b/phpBB/modules/acp/info/acp_styles.php new file mode 100644 index 0000000000..db67167e39 --- /dev/null +++ b/phpBB/modules/acp/info/acp_styles.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_styles_info +{ + function module() + { + return array( + 'filename' => 'acp_styles', + 'title' => 'ACP_CAT_STYLES', + 'version' => '1.0.0', + 'modes' => array( + 'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')), + 'template' => array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + 'theme' => array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + 'imageset' => array('title' => 'ACP_IMAGESETS', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_update.php b/phpBB/modules/acp/info/acp_update.php new file mode 100644 index 0000000000..886cdc94d5 --- /dev/null +++ b/phpBB/modules/acp/info/acp_update.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_update_info +{ + function module() + { + return array( + 'filename' => 'acp_update', + 'title' => 'ACP_UPDATE', + 'version' => '1.0.0', + 'modes' => array( + 'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_users.php b/phpBB/modules/acp/info/acp_users.php new file mode 100644 index 0000000000..0cd5f7ae97 --- /dev/null +++ b/phpBB/modules/acp/info/acp_users.php @@ -0,0 +1,46 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_users_info +{ + function module() + { + return array( + 'filename' => 'acp_users', + 'title' => 'ACP_USER_MANAGEMENT', + 'version' => '1.0.0', + 'modes' => array( + 'overview' => array('title' => 'ACP_MANAGE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')), + 'feedback' => array('title' => 'ACP_USER_FEEDBACK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'profile' => array('title' => 'ACP_USER_PROFILE', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'prefs' => array('title' => 'ACP_USER_PREFS', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'avatar' => array('title' => 'ACP_USER_AVATAR', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'rank' => array('title' => 'ACP_USER_RANK', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'sig' => array('title' => 'ACP_USER_SIG', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'groups' => array('title' => 'ACP_USER_GROUPS', 'auth' => 'acl_a_user && acl_a_group', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'perm' => array('title' => 'ACP_USER_PERM', 'auth' => 'acl_a_user && acl_a_viewauth', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + 'attach' => array('title' => 'ACP_USER_ATTACH', 'auth' => 'acl_a_user', 'display' => false, 'cat' => array('ACP_CAT_USERS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/acp/info/acp_words.php b/phpBB/modules/acp/info/acp_words.php new file mode 100644 index 0000000000..a2417f8a7f --- /dev/null +++ b/phpBB/modules/acp/info/acp_words.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package acp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class acp_words_info +{ + function module() + { + return array( + 'filename' => 'acp_words', + 'title' => 'ACP_WORDS', + 'version' => '1.0.0', + 'modes' => array( + 'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_ban.php b/phpBB/modules/mcp/info/mcp_ban.php new file mode 100644 index 0000000000..383df30498 --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_ban.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_ban_info +{ + function module() + { + return array( + 'filename' => 'mcp_ban', + 'title' => 'MCP_BAN', + 'version' => '1.0.0', + 'modes' => array( + 'user' => array('title' => 'MCP_BAN_USERNAMES', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + 'ip' => array('title' => 'MCP_BAN_IPS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + 'email' => array('title' => 'MCP_BAN_EMAILS', 'auth' => 'acl_m_ban', 'cat' => array('MCP_BAN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_logs.php b/phpBB/modules/mcp/info/mcp_logs.php new file mode 100644 index 0000000000..fe2f9fa1d7 --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_logs.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_logs_info +{ + function module() + { + return array( + 'filename' => 'mcp_logs', + 'title' => 'MCP_LOGS', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_LOGS_FRONT', 'auth' => 'acl_m_ || aclf_m_', 'cat' => array('MCP_LOGS')), + 'forum_logs' => array('title' => 'MCP_LOGS_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), + 'topic_logs' => array('title' => 'MCP_LOGS_TOPIC_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_LOGS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_main.php b/phpBB/modules/mcp/info/mcp_main.php new file mode 100644 index 0000000000..9755cdfc07 --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_main.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_main_info +{ + function module() + { + return array( + 'filename' => 'mcp_main', + 'title' => 'MCP_MAIN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_MAIN_FRONT', 'auth' => '', 'cat' => array('MCP_MAIN')), + 'forum_view' => array('title' => 'MCP_MAIN_FORUM_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), + 'topic_view' => array('title' => 'MCP_MAIN_TOPIC_VIEW', 'auth' => 'acl_m_,$id', 'cat' => array('MCP_MAIN')), + 'post_details' => array('title' => 'MCP_MAIN_POST_DETAILS', 'auth' => 'acl_m_,$id || (!$id && aclf_m_)', 'cat' => array('MCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_notes.php b/phpBB/modules/mcp/info/mcp_notes.php new file mode 100644 index 0000000000..afe232e5b5 --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_notes.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_notes_info +{ + function module() + { + return array( + 'filename' => 'mcp_notes', + 'title' => 'MCP_NOTES', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_NOTES_FRONT', 'auth' => '', 'cat' => array('MCP_NOTES')), + 'user_notes' => array('title' => 'MCP_NOTES_USER', 'auth' => '', 'cat' => array('MCP_NOTES')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_queue.php b/phpBB/modules/mcp/info/mcp_queue.php new file mode 100644 index 0000000000..7a256642b9 --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_queue.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_queue_info +{ + function module() + { + return array( + 'filename' => 'mcp_queue', + 'title' => 'MCP_QUEUE', + 'version' => '1.0.0', + 'modes' => array( + 'unapproved_topics' => array('title' => 'MCP_QUEUE_UNAPPROVED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), + 'unapproved_posts' => array('title' => 'MCP_QUEUE_UNAPPROVED_POSTS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')), + 'approve_details' => array('title' => 'MCP_QUEUE_APPROVE_DETAILS', 'auth' => 'acl_m_approve,$id || (!$id && aclf_m_approve)', 'cat' => array('MCP_QUEUE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_reports.php b/phpBB/modules/mcp/info/mcp_reports.php new file mode 100644 index 0000000000..3893ba5abb --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_reports.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_reports_info +{ + function module() + { + return array( + 'filename' => 'mcp_reports', + 'title' => 'MCP_REPORTS', + 'version' => '1.0.0', + 'modes' => array( + 'reports' => array('title' => 'MCP_REPORTS_OPEN', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'reports_closed' => array('title' => 'MCP_REPORTS_CLOSED', 'auth' => 'aclf_m_report', 'cat' => array('MCP_REPORTS')), + 'report_details' => array('title' => 'MCP_REPORT_DETAILS', 'auth' => 'acl_m_report,$id || (!$id && aclf_m_report)', 'cat' => array('MCP_REPORTS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/info/mcp_warn.php b/phpBB/modules/mcp/info/mcp_warn.php new file mode 100644 index 0000000000..2b0b09f75a --- /dev/null +++ b/phpBB/modules/mcp/info/mcp_warn.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class mcp_warn_info +{ + function module() + { + return array( + 'filename' => 'mcp_warn', + 'title' => 'MCP_WARN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'MCP_WARN_FRONT', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'list' => array('title' => 'MCP_WARN_LIST', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'warn_user' => array('title' => 'MCP_WARN_USER', 'auth' => 'aclf_m_warn', 'cat' => array('MCP_WARN')), + 'warn_post' => array('title' => 'MCP_WARN_POST', 'auth' => 'acl_m_warn && acl_f_read,$id', 'cat' => array('MCP_WARN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_ban.php b/phpBB/modules/mcp/mcp_ban.php new file mode 100644 index 0000000000..0e4c8e6726 --- /dev/null +++ b/phpBB/modules/mcp/mcp_ban.php @@ -0,0 +1,216 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* @package mcp +*/ +class mcp_ban +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template, $cache; + + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + // Include the admin banning interface... + include(PHPBB_ROOT_PATH . 'includes/acp/acp_ban.' . PHP_EXT); + + $bansubmit = request::is_set_post('bansubmit'); + $unbansubmit = request::is_set_post('unbansubmit'); + $current_time = time(); + + $user->add_lang(array('acp/ban', 'acp/users')); + $this->tpl_name = 'mcp_ban'; + + // Ban submitted? + if ($bansubmit) + { + // Grab the list of entries + $ban = request_var('ban', '', ($mode === 'user') ? true : false); + + if ($mode === 'user') + { + $ban = utf8_normalize_nfc($ban); + } + + $ban_len = request_var('banlength', 0); + $ban_len_other = request_var('banlengthother', ''); + $ban_exclude = request_var('banexclude', 0); + $ban_reason = utf8_normalize_nfc(request_var('banreason', '', true)); + $ban_give_reason = utf8_normalize_nfc(request_var('bangivereason', '', true)); + + if ($ban) + { + if (confirm_box(true)) + { + user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . '<br /><br /><a href="' . $this->u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>'); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'ban' => $ban, + 'bansubmit' => true, + 'banlength' => $ban_len, + 'banlengthother' => $ban_len_other, + 'banexclude' => $ban_exclude, + 'banreason' => $ban_reason, + 'bangivereason' => $ban_give_reason))); + } + } + } + else if ($unbansubmit) + { + $ban = request_var('unban', array('')); + + if ($ban) + { + if (confirm_box(true)) + { + user_unban($mode, $ban); + + trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . '<br /><br /><a href="' . $this->u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>'); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'unbansubmit' => true, + 'unban' => $ban))); + } + } + } + + // Ban length options + $ban_end_text = array(0 => $user->lang['PERMANENT'], 30 => $user->lang['30_MINS'], 60 => $user->lang['1_HOUR'], 360 => $user->lang['6_HOURS'], 1440 => $user->lang['1_DAY'], 10080 => $user->lang['7_DAYS'], 20160 => $user->lang['2_WEEKS'], 40320 => $user->lang['1_MONTH'], -1 => $user->lang['UNTIL'] . ' -> '); + + $ban_end_options = ''; + foreach ($ban_end_text as $length => $text) + { + $ban_end_options .= '<option value="' . $length . '">' . $text . '</option>'; + } + + // Define language vars + $this->page_title = $user->lang[strtoupper($mode) . '_BAN']; + + $l_ban_explain = $user->lang[strtoupper($mode) . '_BAN_EXPLAIN']; + $l_ban_exclude_explain = $user->lang[strtoupper($mode) . '_BAN_EXCLUDE_EXPLAIN']; + $l_unban_title = $user->lang[strtoupper($mode) . '_UNBAN']; + $l_unban_explain = $user->lang[strtoupper($mode) . '_UNBAN_EXPLAIN']; + $l_no_ban_cell = $user->lang[strtoupper($mode) . '_NO_BANNED']; + + switch ($mode) + { + case 'user': + $l_ban_cell = $user->lang['USERNAME']; + break; + + case 'ip': + $l_ban_cell = $user->lang['IP_HOSTNAME']; + break; + + case 'email': + $l_ban_cell = $user->lang['EMAIL_ADDRESS']; + break; + } + + acp_ban::display_ban_options($mode); + + $template->assign_vars(array( + 'L_TITLE' => $this->page_title, + 'L_EXPLAIN' => $l_ban_explain, + 'L_UNBAN_TITLE' => $l_unban_title, + 'L_UNBAN_EXPLAIN' => $l_unban_explain, + 'L_BAN_CELL' => $l_ban_cell, + 'L_BAN_EXCLUDE_EXPLAIN' => $l_ban_exclude_explain, + 'L_NO_BAN_CELL' => $l_no_ban_cell, + + 'S_USERNAME_BAN' => ($mode == 'user') ? true : false, + + 'U_ACTION' => $this->u_action, + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=mcp_ban&field=ban'), + )); + + if ($mode === 'email' && !$auth->acl_get('a_user')) + { + return; + } + + // As a "service" we will check if any post id is specified and populate the username of the poster id if given + $post_id = request_var('p', 0); + $user_id = request_var('u', 0); + $username = $pre_fill = false; + + if ($user_id && $user_id <> ANONYMOUS) + { + $sql = 'SELECT username, user_email, user_ip + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = $db->sql_query($sql); + switch ($mode) + { + case 'user': + $pre_fill = (string) $db->sql_fetchfield('username'); + break; + + case 'ip': + $pre_fill = (string) $db->sql_fetchfield('user_ip'); + break; + + case 'email': + $pre_fill = (string) $db->sql_fetchfield('user_email'); + break; + } + $db->sql_freeresult($result); + } + else if ($post_id) + { + $post_info = get_post_data($post_id, 'm_ban'); + + if (sizeof($post_info) && !empty($post_info[$post_id])) + { + switch ($mode) + { + case 'user': + $pre_fill = $post_info[$post_id]['username']; + break; + + case 'ip': + $pre_fill = $post_info[$post_id]['poster_ip']; + break; + + case 'email': + $pre_fill = $post_info[$post_id]['user_email']; + break; + } + + } + } + + if ($pre_fill) + { + $template->assign_var('BAN_QUANTIFIER', $pre_fill); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_forum.php b/phpBB/modules/mcp/mcp_forum.php new file mode 100644 index 0000000000..ef28d5efd0 --- /dev/null +++ b/phpBB/modules/mcp/mcp_forum.php @@ -0,0 +1,449 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* MCP Forum View +*/ +function mcp_forum_view($id, $mode, $action, $forum_info) +{ + global $template, $db, $user, $auth, $cache, $module, $config; + + $user->add_lang(array('viewtopic', 'viewforum')); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + // merge_topic is the quickmod action, merge_topics is the mcp_forum action, and merge_select is the mcp_topic action + $merge_select = ($action == 'merge_select' || $action == 'merge_topic' || $action == 'merge_topics') ? true : false; + + if ($merge_select) + { + // Fixes a "bug" that makes forum_view use the same ordering as topic_view + request::overwrite('sk', null, request::POST); + request::overwrite('sd', null, request::POST); + request::overwrite('sk', null, request::REQUEST); + request::overwrite('sd', null, request::REQUEST); + } + + $forum_id = $forum_info['forum_id']; + $start = request_var('start', 0); + $topic_id_list = request_var('topic_id_list', array(0)); + $post_id_list = request_var('post_id_list', array(0)); + $source_topic_ids = array(request_var('t', 0)); + $to_topic_id = request_var('to_topic_id', 0); + + $url_extra = ''; + $url_extra .= ($forum_id) ? "&f=$forum_id" : ''; + $url_extra .= ($GLOBALS['topic_id']) ? '&t=' . $GLOBALS['topic_id'] : ''; + $url_extra .= ($GLOBALS['post_id']) ? '&p=' . $GLOBALS['post_id'] : ''; + $url_extra .= ($GLOBALS['user_id']) ? '&u=' . $GLOBALS['user_id'] : ''; + + $url = ($url_extra) ? append_sid('mcp', $url_extra) : append_sid('mcp'); + + // Resync Topics + switch ($action) + { + case 'resync': + $topic_ids = request_var('topic_id_list', array(0)); + mcp_resync_topics($topic_ids); + break; + + case 'merge_topics': + $source_topic_ids = $topic_id_list; + case 'merge_topic': + if ($to_topic_id) + { + merge_topics($forum_id, $source_topic_ids, $to_topic_id); + } + break; + } + + $selected_ids = ''; + if (sizeof($post_id_list) && $action != 'merge_topics') + { + foreach ($post_id_list as $num => $post_id) + { + $selected_ids .= '&post_id_list[' . $num . ']=' . $post_id; + } + } + else if (sizeof($topic_id_list) && $action == 'merge_topics') + { + foreach ($topic_id_list as $num => $topic_id) + { + $selected_ids .= '&topic_id_list[' . $num . ']=' . $topic_id; + } + } + + make_jumpbox($url . "&i=$id&action=$action&mode=$mode" . (($merge_select) ? $selected_ids : ''), $forum_id, false, 'm_', true); + + $topics_per_page = ($forum_info['forum_topics_per_page']) ? $forum_info['forum_topics_per_page'] : $config['topics_per_page']; + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewforum', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + $template->assign_vars(array( + 'ACTION' => $action, + 'FORUM_NAME' => $forum_info['forum_name'], + 'FORUM_DESCRIPTION' => generate_text_for_display($forum_info['forum_desc'], $forum_info['forum_desc_uid'], $forum_info['forum_desc_bitfield'], $forum_info['forum_desc_options']), + + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'TOPIC_REPORTED'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'TOPIC_UNAPPROVED'), + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), + + 'S_CAN_REPORT' => $auth->acl_get('m_report', $forum_id), + 'S_CAN_DELETE' => $auth->acl_get('m_delete', $forum_id), + 'S_CAN_MERGE' => $auth->acl_get('m_merge', $forum_id), + 'S_CAN_MOVE' => $auth->acl_get('m_move', $forum_id), + 'S_CAN_FORK' => $auth->acl_get('m_', $forum_id), + 'S_CAN_LOCK' => $auth->acl_get('m_lock', $forum_id), + 'S_CAN_SYNC' => $auth->acl_get('m_', $forum_id), + 'S_CAN_APPROVE' => $auth->acl_get('m_approve', $forum_id), + 'S_MERGE_SELECT' => ($merge_select) ? true : false, + 'S_CAN_MAKE_NORMAL' => $auth->acl_gets('f_sticky', 'f_announce', $forum_id), + 'S_CAN_MAKE_STICKY' => $auth->acl_get('f_sticky', $forum_id), + 'S_CAN_MAKE_ANNOUNCE' => $auth->acl_get('f_announce', $forum_id), + + 'U_VIEW_FORUM' => append_sid('viewforum', 'f=' . $forum_id), + 'U_VIEW_FORUM_LOGS' => ($auth->acl_gets('a_', 'm_', $forum_id) && $module->loaded('logs')) ? append_sid('mcp', 'i=logs&mode=forum_logs&f=' . $forum_id) : '', + + 'S_MCP_ACTION' => $url . "&i=$id&forum_action=$action&mode=$mode&start=$start" . (($merge_select) ? $selected_ids : ''), + + 'PAGINATION' => generate_pagination($url . "&i=$id&action=$action&mode=$mode&sd=$sort_dir&sk=$sort_key&st=$sort_days" . (($merge_select) ? $selected_ids : ''), $forum_topics, $topics_per_page, $start), + 'PAGE_NUMBER' => on_page($forum_topics, $topics_per_page, $start), + 'TOTAL_TOPICS' => ($forum_topics == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $forum_topics), + )); + + // Grab icons + $icons = cache::obtain_icons(); + + $topic_rows = array(); + + if ($config['load_db_lastread']) + { + $read_tracking_join = ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id'] . ')'; + $read_tracking_select = ', tt.mark_time'; + } + else + { + $read_tracking_join = $read_tracking_select = ''; + } + + $sql = "SELECT t.topic_id + FROM " . TOPICS_TABLE . " t + WHERE t.forum_id IN($forum_id, 0) + " . (($auth->acl_get('m_approve', $forum_id)) ? '' : 'AND t.topic_approved = 1') . " + $limit_time_sql + ORDER BY t.topic_type DESC, $sort_order_sql"; + $result = $db->sql_query_limit($sql, $topics_per_page, $start); + + $topic_list = $topic_tracking_info = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $sql = "SELECT t.*$read_tracking_select + FROM " . TOPICS_TABLE . " t $read_tracking_join + WHERE " . $db->sql_in_set('t.topic_id', $topic_list, false, true); + + $result = $db->sql_query($sql); + while ($row = $db->sql_fetchrow($result)) + { + $topic_rows[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + + // If there is more than one page, but we have no topic list, then the start parameter is... erm... out of sync + if (!sizeof($topic_list) && $forum_topics && $start > 0) + { + redirect($url . "&i=$id&action=$action&mode=$mode"); + } + + // Get topic tracking info + if (sizeof($topic_list)) + { + if ($config['load_db_lastread']) + { + $topic_tracking_info = get_topic_tracking($forum_id, $topic_list, $topic_rows, array($forum_id => $forum_info['mark_time']), array()); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($forum_id, $topic_list, array()); + } + } + + foreach ($topic_list as $topic_id) + { + $topic_title = ''; + + $row = &$topic_rows[$topic_id]; + + $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; + + if ($row['topic_status'] == ITEM_MOVED) + { + $unread_topic = false; + } + else + { + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + } + + // Get folder img, topic status/type related information + $folder_img = $folder_alt = $topic_type = ''; + topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); + + $topic_title = censor_text($row['topic_title']); + + $topic_unapproved = (!$row['topic_approved'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; + $posts_unapproved = ($row['topic_approved'] && $row['topic_replies'] < $row['topic_replies_real'] && $auth->acl_get('m_approve', $row['forum_id'])) ? true : false; + $u_mcp_queue = ($topic_unapproved || $posts_unapproved) ? $url . '&i=queue&mode=' . (($topic_unapproved) ? 'approve_details' : 'unapproved_posts') . '&t=' . $row['topic_id'] : ''; + + $topic_row = array( + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, 'src'), + 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', + 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', + 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', + 'UNAPPROVED_IMG' => ($topic_unapproved || $posts_unapproved) ? $user->img('icon_topic_unapproved', ($topic_unapproved) ? 'TOPIC_UNAPPROVED' : 'POSTS_UNAPPROVED') : '', + + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + + 'TOPIC_TYPE' => $topic_type, + 'TOPIC_TITLE' => $topic_title, + 'REPLIES' => ($auth->acl_get('m_approve', $row['forum_id'])) ? $row['topic_replies_real'] : $row['topic_replies'], + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + + 'S_TOPIC_REPORTED' => (!empty($row['topic_reported']) && empty($row['topic_moved_id']) && $auth->acl_get('m_report', $row['forum_id'])) ? true : false, + 'S_TOPIC_UNAPPROVED' => $topic_unapproved, + 'S_POSTS_UNAPPROVED' => $posts_unapproved, + 'S_UNREAD_TOPIC' => $unread_topic, + ); + + if ($row['topic_status'] == ITEM_MOVED) + { + $topic_row = array_merge($topic_row, array( + 'U_VIEW_TOPIC' => append_sid('viewtopic', "t={$row['topic_moved_id']}"), + 'U_DELETE_TOPIC' => ($auth->acl_get('m_delete', $forum_id)) ? append_sid('mcp', "i=$id&f=$forum_id&topic_id_list[]={$row['topic_id']}&mode=forum_view&action=delete_topic") : '', + 'S_MOVED_TOPIC' => true, + 'TOPIC_ID' => $row['topic_moved_id'], + )); + } + else + { + if ($action == 'merge_topic' || $action == 'merge_topics') + { + $u_select_topic = $url . "&i=$id&mode=forum_view&action=$action&to_topic_id=" . $row['topic_id'] . $selected_ids; + } + else + { + $u_select_topic = $url . "&i=$id&mode=topic_view&action=merge&to_topic_id=" . $row['topic_id'] . $selected_ids; + } + $topic_row = array_merge($topic_row, array( + 'U_VIEW_TOPIC' => append_sid('mcp', "i=$id&f=$forum_id&t={$row['topic_id']}&mode=topic_view"), + + 'S_SELECT_TOPIC' => ($merge_select && !in_array($row['topic_id'], $source_topic_ids)) ? true : false, + 'U_SELECT_TOPIC' => $u_select_topic, + 'U_MCP_QUEUE' => $u_mcp_queue, + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $forum_id)) ? append_sid('mcp', 'i=main&mode=topic_view&t=' . $row['topic_id'] . '&action=reports') : '', + 'TOPIC_ID' => $row['topic_id'], + 'S_TOPIC_CHECKED' => ($topic_id_list && in_array($row['topic_id'], $topic_id_list)) ? true : false, + )); + } + + $template->assign_block_vars('topicrow', $topic_row); + } + unset($topic_rows); +} + +/** +* Resync topics +*/ +function mcp_resync_topics($topic_ids) +{ + global $auth, $db, $template, $user; + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + { + return; + } + + // Sync everything and perform extra checks separately + sync('topic_reported', 'topic_id', $topic_ids, false, true); + sync('topic_attachment', 'topic_id', $topic_ids, false, true); + sync('topic', 'topic_id', $topic_ids, true, false); + + $sql = 'SELECT topic_id, forum_id, topic_title + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + // Log this action + while ($row = $db->sql_fetchrow($result)) + { + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_TOPIC_RESYNC', $row['topic_title']); + } + $db->sql_freeresult($result); + + $msg = (sizeof($topic_ids) == 1) ? $user->lang['TOPIC_RESYNC_SUCCESS'] : $user->lang['TOPICS_RESYNC_SUCCESS']; + + $redirect = request_var('redirect', $user->data['session_page']); + + meta_refresh(3, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + + return; +} + +/** +* Merge selected topics into selected topic +*/ +function merge_topics($forum_id, $topic_ids, $to_topic_id) +{ + global $db, $template, $user, $auth; + + if (!sizeof($topic_ids)) + { + $template->assign_var('MESSAGE', $user->lang['NO_TOPIC_SELECTED']); + return; + } + if (!$to_topic_id) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($topic_data)) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = $topic_data[$to_topic_id]; + + $post_id_list = request_var('post_id_list', array(0)); + $start = request_var('start', 0); + + if (!sizeof($post_id_list) && sizeof($topic_ids)) + { + $sql = 'SELECT post_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $result = $db->sql_query($sql); + + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_id_list[] = $row['post_id']; + } + $db->sql_freeresult($result); + } + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'f' => $forum_id, + 'post_id_list' => $post_id_list, + 'to_topic_id' => $to_topic_id, + 'mode' => 'forum_view', + 'action' => 'merge_topics', + 'start' => $start, + 'redirect' => $redirect, + 'topic_id_list' => $topic_ids) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + $to_forum_id = $topic_data['forum_id']; + + move_posts($post_id_list, $to_topic_id); + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + + // Message and return links + $success_msg = 'POSTS_MERGED_SUCCESS'; + + // If the topic no longer exist, we will update the topic watch table. + // To not let it error out on users watching both topics, we just return on an error... + $db->sql_return_on_error(true); + $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); + $db->sql_return_on_error(false); + + $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids)); + + // Link to the new topic + $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid('viewtopic', 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, 'MERGE_TOPICS', $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid('viewtopic', "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_front.php b/phpBB/modules/mcp/mcp_front.php new file mode 100644 index 0000000000..4b229c616f --- /dev/null +++ b/phpBB/modules/mcp/mcp_front.php @@ -0,0 +1,282 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* MCP Front Panel +*/ +function mcp_front_view($id, $mode, $action) +{ + global $template, $db, $user, $auth, $module, $config; + + // Latest 5 unapproved + if ($module->loaded('queue')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))); + $post_list = array(); + $forum_names = array(); + + $forum_id = request_var('f', 0); + + $template->assign_var('S_SHOW_UNAPPROVED', (!empty($forum_list)) ? true : false); + + if (!empty($forum_list)) + { + $sql = 'SELECT COUNT(post_id) AS total + FROM ' . POSTS_TABLE . ' + WHERE forum_id IN (0, ' . implode(', ', $forum_list) . ') + AND post_approved = 0'; + $result = $db->sql_query($sql); + $total = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + + if ($total) + { + $global_id = $forum_list[0]; + + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_list); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + + $sql = 'SELECT post_id + FROM ' . POSTS_TABLE . ' + WHERE forum_id IN (0, ' . implode(', ', $forum_list) . ') + AND post_approved = 0 + ORDER BY post_time DESC'; + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $post_list[] = $row['post_id']; + } + $db->sql_freeresult($result); + + if (empty($post_list)) + { + $total = 0; + } + } + + if ($total) + { + $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.username, u.username_clean, u.user_colour, t.topic_id, t.topic_title, t.topic_first_post_id, p.forum_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('p.post_id', $post_list) . ' + AND t.topic_id = p.topic_id + AND p.poster_id = u.user_id + ORDER BY p.post_time DESC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('unapproved', array( + 'U_POST_DETAILS' => append_sid('mcp', 'i=queue&mode=approve_details&f=' . $row['forum_id'] . '&p=' . $row['post_id']), + 'U_MCP_FORUM' => (!$global_topic) ? append_sid('mcp', 'i=main&mode=forum_view&f=' . $row['forum_id']) : '', + 'U_MCP_TOPIC' => append_sid('mcp', 'i=main&mode=topic_view&f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + 'U_FORUM' => (!$global_topic) ? append_sid('viewforum', 'f=' . $row['forum_id']) : '', + 'U_TOPIC' => append_sid('viewtopic', 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + + 'AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour']), + 'AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour']), + 'U_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_ID' => $row['post_id'], + 'TOPIC_TITLE' => $row['topic_title'], + 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_TIME' => $user->format_date($row['post_time'])) + ); + } + $db->sql_freeresult($result); + } + + $template->assign_vars(array( + 'S_MCP_QUEUE_ACTION' => append_sid('mcp', 'i=queue'), + )); + + if ($total == 0) + { + $template->assign_vars(array( + 'L_UNAPPROVED_TOTAL' => $user->lang['UNAPPROVED_POSTS_ZERO_TOTAL'], + 'S_HAS_UNAPPROVED_POSTS' => false) + ); + } + else + { + $template->assign_vars(array( + 'L_UNAPPROVED_TOTAL' => ($total == 1) ? $user->lang['UNAPPROVED_POST_TOTAL'] : sprintf($user->lang['UNAPPROVED_POSTS_TOTAL'], $total), + 'S_HAS_UNAPPROVED_POSTS' => true) + ); + } + } + } + + // Latest 5 reported + if ($module->loaded('reports')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_report'))); + + $template->assign_var('S_SHOW_REPORTS', (!empty($forum_list)) ? true : false); + + if (!empty($forum_list)) + { + $sql = 'SELECT COUNT(r.report_id) AS total + FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p + WHERE r.post_id = p.post_id + AND r.report_closed = 0 + AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')'; + $result = $db->sql_query($sql); + $total = (int) $db->sql_fetchfield('total'); + $db->sql_freeresult($result); + + if ($total) + { + $global_id = $forum_list[0]; + + $sql = $db->sql_build_query('SELECT', array( + 'SELECT' => 'r.report_time, p.post_id, p.post_subject, p.post_time, u.username, u.username_clean, u.user_colour, u.user_id, u2.username as author_name, u2.username_clean as author_name_clean, u2.user_colour as author_colour, u2.user_id as author_id, t.topic_id, t.topic_title, f.forum_id, f.forum_name', + + 'FROM' => array( + REPORTS_TABLE => 'r', + REPORTS_REASONS_TABLE => 'rr', + TOPICS_TABLE => 't', + USERS_TABLE => array('u', 'u2'), + POSTS_TABLE => 'p' + ), + + 'LEFT_JOIN' => array( + array( + 'FROM' => array(FORUMS_TABLE => 'f'), + 'ON' => 'f.forum_id = p.forum_id' + ) + ), + + 'WHERE' => 'r.post_id = p.post_id + AND r.report_closed = 0 + AND r.reason_id = rr.reason_id + AND p.topic_id = t.topic_id + AND r.user_id = u.user_id + AND p.poster_id = u2.user_id + AND p.forum_id IN (0, ' . implode(', ', $forum_list) . ')', + + 'ORDER_BY' => 'p.post_time DESC' + )); + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('report', array( + 'U_POST_DETAILS' => append_sid('mcp', 'f=' . $row['forum_id'] . '&p=' . $row['post_id'] . "&i=reports&mode=report_details"), + 'U_MCP_FORUM' => (!$global_topic) ? append_sid('mcp', 'f=' . $row['forum_id'] . "&i=$id&mode=forum_view") : '', + 'U_MCP_TOPIC' => append_sid('mcp', 'f=' . $row['forum_id'] . '&t=' . $row['topic_id'] . "&i=$id&mode=topic_view"), + 'U_FORUM' => (!$global_topic) ? append_sid('viewforum', 'f=' . $row['forum_id']) : '', + 'U_TOPIC' => append_sid('viewtopic', 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + + 'REPORTER_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']), + 'U_REPORTER' => get_username_string('profile', $row['user_id'], $row['username'], $row['user_colour']), + + 'AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['author_name'], $row['author_colour']), + 'AUTHOR' => get_username_string('username', $row['author_id'], $row['author_name'], $row['author_colour']), + 'AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['author_name'], $row['author_colour']), + 'U_AUTHOR' => get_username_string('profile', $row['author_id'], $row['author_name'], $row['author_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $row['forum_name'] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'TOPIC_TITLE' => $row['topic_title'], + 'SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'POST_TIME' => $user->format_date($row['post_time']), + )); + } + } + + if ($total == 0) + { + $template->assign_vars(array( + 'L_REPORTS_TOTAL' => $user->lang['REPORTS_ZERO_TOTAL'], + 'S_HAS_REPORTS' => false) + ); + } + else + { + $template->assign_vars(array( + 'L_REPORTS_TOTAL' => ($total == 1) ? $user->lang['REPORT_TOTAL'] : sprintf($user->lang['REPORTS_TOTAL'], $total), + 'S_HAS_REPORTS' => true) + ); + } + } + } + + // Latest 5 logs + if ($module->loaded('logs')) + { + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); + + if (!empty($forum_list)) + { + // Add forum_id 0 for global announcements + $forum_list[] = 0; + + $log_count = 0; + $log = array(); + view_log('mod', $log, $log_count, 5, 0, $forum_list); + + foreach ($log as $row) + { + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'TIME' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'U_VIEW_TOPIC' => (!empty($row['viewtopic'])) ? $row['viewtopic'] : '', + 'U_VIEWLOGS' => (!empty($row['viewlogs'])) ? $row['viewlogs'] : '') + ); + } + } + + $template->assign_vars(array( + 'S_SHOW_LOGS' => (!empty($forum_list)) ? true : false, + 'S_HAS_LOGS' => (!empty($log)) ? true : false) + ); + } + + $template->assign_var('S_MCP_ACTION', append_sid('mcp')); + make_jumpbox(append_sid('mcp', 'i=main&mode=forum_view'), 0, false, 'm_', true); +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_logs.php b/phpBB/modules/mcp/mcp_logs.php new file mode 100644 index 0000000000..22b413279f --- /dev/null +++ b/phpBB/modules/mcp/mcp_logs.php @@ -0,0 +1,213 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_logs +* Handling warning the users +* @package mcp +*/ +class mcp_logs +{ + var $u_action; + var $p_master; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $config; + + $user->add_lang('acp/common'); + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + else + { + $action = request_var('action', ''); + } + + // Set up general vars + $start = request_var('start', 0); + $deletemark = ($action == 'del_marked') ? true : false; + $deleteall = ($action == 'del_all') ? true : false; + $marked = request_var('mark', array(0)); + + // Sort keys + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + $this->tpl_name = 'mcp_logs'; + $this->page_title = 'MCP_LOGS'; + + $forum_list = array_values(array_intersect(get_forum_list('f_read'), get_forum_list('m_'))); + $forum_list[] = 0; + + $forum_id = $topic_id = 0; + + switch ($mode) + { + case 'front': + break; + + case 'forum_logs': + $forum_id = request_var('f', 0); + + if (!in_array($forum_id, $forum_list)) + { + trigger_error('NOT_AUTHORISED'); + } + + $forum_list = array($forum_id); + break; + + case 'topic_logs': + $topic_id = request_var('t', 0); + + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + $forum_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + if (!in_array($forum_id, $forum_list)) + { + trigger_error('NOT_AUTHORISED'); + } + + $forum_list = array($forum_id); + break; + } + + // Delete entries if requested and able + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + if (confirm_box(true)) + { + if ($deletemark && sizeof($marked)) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_MOD . ' + AND ' . $db->sql_in_set('forum_id', $forum_list) . ' + AND ' . $db->sql_in_set('log_id', $marked); + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_MOD'); + } + else if ($deleteall) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_MOD . ' + AND ' . $db->sql_in_set('forum_id', $forum_list); + + if ($mode == 'topic_logs') + { + $sql .= ' AND topic_id = ' . $topic_id; + } + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_MOD'); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'f' => $forum_id, + 't' => $topic_id, + 'start' => $start, + 'delmarked' => $deletemark, + 'delall' => $deleteall, + 'mark' => $marked, + 'st' => $sort_days, + 'sk' => $sort_key, + 'sd' => $sort_dir, + 'i' => $id, + 'mode' => $mode, + 'action' => request_var('action', array('' => '')))) + ); + } + } + + // Sorting + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('u' => $user->lang['SORT_USERNAME'], 't' => $user->lang['SORT_DATE'], 'i' => $user->lang['SORT_IP'], 'o' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0; + $sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + + // Grab log data + $log_data = array(); + $log_count = 0; + view_log('mod', $log_data, $log_count, $config['topics_per_page'], $start, $forum_list, $topic_id, 0, $sql_where, $sql_sort); + + $template->assign_vars(array( + 'PAGE_NUMBER' => on_page($log_count, $config['topics_per_page'], $start), + 'TOTAL' => ($log_count == 1) ? $user->lang['TOTAL_LOG'] : sprintf($user->lang['TOTAL_LOGS'], $log_count), + 'PAGINATION' => generate_pagination($this->u_action . "&$u_sort_param", $log_count, $config['topics_per_page'], $start), + + 'L_TITLE' => $user->lang['MCP_LOGS'], + + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + 'S_LOGS' => ($log_count > 0), + ) + ); + + foreach ($log_data as $row) + { + $data = array(); + + $checks = array('viewtopic', 'viewforum'); + foreach ($checks as $check) + { + if (isset($row[$check]) && $row[$check]) + { + $data[] = '<a href="' . $row[$check] . '">' . $user->lang['LOGVIEW_' . strtoupper($check)] . '</a>'; + } + } + + $template->assign_block_vars('log', array( + 'USERNAME' => $row['username_full'], + 'IP' => $row['ip'], + 'DATE' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'DATA' => (sizeof($data)) ? implode(' | ', $data) : '', + 'ID' => $row['id'], + ) + ); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_main.php b/phpBB/modules/mcp/mcp_main.php new file mode 100644 index 0000000000..217ff7c896 --- /dev/null +++ b/phpBB/modules/mcp/mcp_main.php @@ -0,0 +1,1220 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_main +* Handling mcp actions +* @package mcp +*/ +class mcp_main +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $action, $config; + + $quickmod = ($mode == 'quickmod') ? true : false; + + switch ($action) + { + case 'lock': + case 'unlock': + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + lock_unlock($action, $topic_ids); + break; + + case 'lock_post': + case 'unlock_post': + + $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); + + if (!sizeof($post_ids)) + { + trigger_error('NO_POST_SELECTED'); + } + + lock_unlock($action, $post_ids); + break; + + case 'make_announce': + case 'make_sticky': + case 'make_global': + case 'make_normal': + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + change_topic_type($action, $topic_ids); + break; + + case 'move': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_move_topic($topic_ids); + break; + + case 'fork': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_fork_topic($topic_ids); + break; + + case 'delete_topic': + $user->add_lang('viewtopic'); + + $topic_ids = (!$quickmod) ? request_var('topic_id_list', array(0)) : array(request_var('t', 0)); + + if (!sizeof($topic_ids)) + { + trigger_error('NO_TOPIC_SELECTED'); + } + + mcp_delete_topic($topic_ids); + break; + + case 'delete_post': + $user->add_lang('posting'); + + $post_ids = (!$quickmod) ? request_var('post_id_list', array(0)) : array(request_var('p', 0)); + + if (!sizeof($post_ids)) + { + trigger_error('NO_POST_SELECTED'); + } + + mcp_delete_post($post_ids); + break; + } + + switch ($mode) + { + case 'front': + include(PHPBB_ROOT_PATH . 'includes/mcp/mcp_front.' . PHP_EXT); + + $user->add_lang('acp/common'); + + mcp_front_view($id, $mode, $action); + + $this->tpl_name = 'mcp_front'; + $this->page_title = 'MCP_MAIN'; + break; + + case 'forum_view': + include(PHPBB_ROOT_PATH . 'includes/mcp/mcp_forum.' . PHP_EXT); + + $user->add_lang('viewforum'); + + $forum_id = request_var('f', 0); + + $forum_info = get_forum_data($forum_id, 'm_', true); + + if (!sizeof($forum_info)) + { + $this->main('main', 'front'); + return; + } + + $forum_info = $forum_info[$forum_id]; + + mcp_forum_view($id, $mode, $action, $forum_info); + + $this->tpl_name = 'mcp_forum'; + $this->page_title = 'MCP_MAIN_FORUM_VIEW'; + break; + + case 'topic_view': + include(PHPBB_ROOT_PATH . 'includes/mcp/mcp_topic.' . PHP_EXT); + + mcp_topic_view($id, $mode, $action); + + $this->tpl_name = 'mcp_topic'; + $this->page_title = 'MCP_MAIN_TOPIC_VIEW'; + break; + + case 'post_details': + include(PHPBB_ROOT_PATH . 'includes/mcp/mcp_post.' . PHP_EXT); + + mcp_post_details($id, $mode, $action); + + $this->tpl_name = ($action == 'whois') ? 'mcp_whois' : 'mcp_post'; + $this->page_title = 'MCP_MAIN_POST_DETAILS'; + break; + + default: + trigger_error('NO_MODE', E_USER_ERROR); + break; + } + } +} + +/** +* Lock/Unlock Topic/Post +*/ +function lock_unlock($action, $ids) +{ + global $auth, $user, $db; + + if ($action == 'lock' || $action == 'unlock') + { + $table = TOPICS_TABLE; + $sql_id = 'topic_id'; + $set_id = 'topic_status'; + $l_prefix = 'TOPIC'; + } + else + { + $table = POSTS_TABLE; + $sql_id = 'post_id'; + $set_id = 'post_edit_locked'; + $l_prefix = 'POST'; + } + + $orig_ids = $ids; + + if (!check_ids($ids, $table, $sql_id, array('m_lock'))) + { + // Make sure that for f_user_lock only the lock action is triggered. + if ($action != 'lock') + { + return; + } + + $ids = $orig_ids; + + if (!check_ids($ids, $table, $sql_id, array('f_user_lock'))) + { + return; + } + } + unset($orig_ids); + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + $sql_id . '_list' => $ids, + 'action' => $action, + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + $sql = "UPDATE $table + SET $set_id = " . (($action == 'lock' || $action == 'lock_post') ? ITEM_LOCKED : ITEM_UNLOCKED) . ' + WHERE ' . $db->sql_in_set($sql_id, $ids); + $db->sql_query($sql); + + $data = ($action == 'lock' || $action == 'unlock') ? get_topic_data($ids) : get_post_data($ids); + + foreach ($data as $id => $row) + { + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_' . strtoupper($action), $row['topic_title']); + } + + $success_msg = $l_prefix . ((sizeof($ids) == 1) ? '' : 'S') . '_' . (($action == 'lock' || $action == 'lock_post') ? 'LOCKED' : 'UNLOCKED') . '_SUCCESS'; + } + else + { + confirm_box(false, strtoupper($action) . '_' . $l_prefix . ((sizeof($ids) == 1) ? '' : 'S'), $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(2, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Change Topic Type +*/ +function change_topic_type($action, $topic_ids) +{ + global $auth, $user, $db; + + // For changing topic types, we only allow operations in one forum. + $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('f_announce', 'f_sticky', 'm_'), true); + + if ($forum_id === false) + { + return; + } + + switch ($action) + { + case 'make_announce': + $new_topic_type = POST_ANNOUNCE; + $check_acl = 'f_announce'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_ANNOUNCEMENT' : 'MCP_MAKE_ANNOUNCEMENTS'; + break; + + case 'make_global': + $new_topic_type = POST_GLOBAL; + $check_acl = 'f_announce'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_GLOBAL' : 'MCP_MAKE_GLOBALS'; + break; + + case 'make_sticky': + $new_topic_type = POST_STICKY; + $check_acl = 'f_sticky'; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_STICKY' : 'MCP_MAKE_STICKIES'; + break; + + default: + $new_topic_type = POST_NORMAL; + $check_acl = ''; + $l_new_type = (sizeof($topic_ids) == 1) ? 'MCP_MAKE_NORMAL' : 'MCP_MAKE_NORMALS'; + break; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + + $s_hidden_fields = array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => $action, + 'redirect' => $redirect, + ); + $success_msg = ''; + + if (confirm_box(true)) + { + if ($new_topic_type != POST_GLOBAL) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id <> 0'; + $db->sql_query($sql); + + // Reset forum id if a global topic is within the array + $to_forum_id = request_var('to_forum_id', 0); + + if ($to_forum_id) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type, forum_id = $to_forum_id + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $db->sql_query($sql); + + // Update forum_ids for all posts + $sql = 'UPDATE ' . POSTS_TABLE . " + SET forum_id = $to_forum_id + WHERE " . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $db->sql_query($sql); + + // Do a little forum sync stuff + $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $to_forum_id); + } + } + else + { + // Get away with those topics already being a global announcement by re-calculating $topic_ids + $sql = 'SELECT topic_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id <> 0'; + $result = $db->sql_query($sql); + + $topic_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_ids[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + // Delete topic shadows for global announcements + $sql = 'DELETE FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_moved_id', $topic_ids); + $db->sql_query($sql); + + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_type = $new_topic_type, forum_id = 0 + WHERE " . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + + // Update forum_ids for all posts + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET forum_id = 0 + WHERE ' . $db->sql_in_set('topic_id', $topic_ids); + $db->sql_query($sql); + + // Do a little forum sync stuff + $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts, COUNT(t.topic_approved) as topics_authed + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; + } + + if ($row_data['topics_authed']) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $row_data['topics_authed']; + } + + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) sizeof($topic_ids); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $forum_id); + } + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_TYPE_CHANGED' : 'TOPICS_TYPE_CHANGED'; + + if (sizeof($topic_ids)) + { + $data = get_topic_data($topic_ids); + + foreach ($data as $topic_id => $row) + { + add_log('mod', $forum_id, $topic_id, 'LOG_TOPIC_TYPE_CHANGED', $row['topic_title']); + } + } + } + else + { + // Global topic involved? + $global_involved = false; + + if ($new_topic_type != POST_GLOBAL) + { + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_ids) . ' + AND forum_id = 0'; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $global_involved = true; + } + } + + if ($global_involved) + { + global $template; + + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select(request_var('f', $forum_id), false, false, true, true), + 'S_CAN_LEAVE_SHADOW' => false, + 'ADDITIONAL_MSG' => (sizeof($topic_ids) == 1) ? $user->lang['SELECT_FORUM_GLOBAL_ANNOUNCEMENT'] : $user->lang['SELECT_FORUM_GLOBAL_ANNOUNCEMENTS']) + ); + + confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields), 'mcp_move.html'); + } + else + { + confirm_box(false, $l_new_type, build_hidden_fields($s_hidden_fields)); + } + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(2, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Move Topic +*/ +function mcp_move_topic($topic_ids) +{ + global $auth, $user, $db, $template; + + // Here we limit the operation to one forum only + $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true); + + if ($forum_id === false) + { + return; + } + + $to_forum_id = request_var('to_forum_id', 0); + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $additional_msg = $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'move', + 'redirect' => $redirect) + ); + + if ($to_forum_id) + { + $forum_data = get_forum_data($to_forum_id, 'f_post'); + + if (!sizeof($forum_data)) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + else + { + $forum_data = $forum_data[$to_forum_id]; + + if ($forum_data['forum_type'] != FORUM_POST) + { + $additional_msg = $user->lang['FORUM_NOT_POSTABLE']; + } + else if (!$auth->acl_get('f_post', $to_forum_id)) + { + $additional_msg = $user->lang['USER_CANNOT_POST']; + } + else if ($forum_id == $to_forum_id) + { + $additional_msg = $user->lang['CANNOT_MOVE_SAME_FORUM']; + } + } + } + else if (request::is_set_post('confirm')) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + + if ($to_forum_id && !$additional_msg && confirm_box(true)) + { + $topic_data = get_topic_data($topic_ids); + $leave_shadow = request::is_set_post('move_leave_shadow'); + + $topics_moved = sizeof($topic_ids); + $topics_authed_moved = 0; + $forum_sync_data = array(); + + $forum_sync_data[$forum_id] = current($topic_data); + $forum_sync_data[$to_forum_id] = $forum_data; + + foreach ($topic_data as $topic_id => $topic_info) + { + if ($topic_info['topic_approved'] == '1') + { + $topics_authed_moved++; + } + } + + $db->sql_transaction('begin'); + + $sql = 'SELECT SUM(t.topic_replies + t.topic_approved) as topic_posts + FROM ' . TOPICS_TABLE . ' t + WHERE ' . $db->sql_in_set('t.topic_id', $topic_ids); + $result = $db->sql_query($sql); + $row_data = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $sync_sql = array(); + + if ($row_data['topic_posts']) + { + $sync_sql[$forum_id][] = 'forum_posts = forum_posts - ' . (int) $row_data['topic_posts']; + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . (int) $row_data['topic_posts']; + } + + if ($topics_authed_moved) + { + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . (int) $topics_authed_moved; + } + + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . (int) $topics_moved; + + // Move topics, but do not resync yet + move_topics($topic_ids, $to_forum_id, false); + + $forum_ids = array($to_forum_id); + foreach ($topic_data as $topic_id => $row) + { + // Get the list of forums to resync, add a log entry + $forum_ids[] = $row['forum_id']; + add_log('mod', $to_forum_id, $topic_id, 'LOG_MOVE', $row['forum_name'], $forum_data['forum_name']); + + // If we have moved a global announcement, we need to correct the topic type + if ($row['topic_type'] == POST_GLOBAL) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_type = ' . POST_ANNOUNCE . ' + WHERE topic_id = ' . (int) $row['topic_id']; + $db->sql_query($sql); + } + + // Leave a redirection if required and only if the topic is visible to users + if ($leave_shadow && $row['topic_approved'] && $row['topic_type'] != POST_GLOBAL) + { + $shadow = array( + 'forum_id' => (int) $row['forum_id'], + 'icon_id' => (int) $row['icon_id'], + 'topic_attachment' => (int) $row['topic_attachment'], + 'topic_approved' => 1, // a shadow topic is always approved + 'topic_reported' => 0, // a shadow topic is never reported + 'topic_title' => (string) $row['topic_title'], + 'topic_poster' => (int) $row['topic_poster'], + 'topic_time' => (int) $row['topic_time'], + 'topic_time_limit' => (int) $row['topic_time_limit'], + 'topic_views' => (int) $row['topic_views'], + 'topic_replies' => (int) $row['topic_replies'], + 'topic_replies_real' => (int) $row['topic_replies_real'], + 'topic_status' => ITEM_MOVED, + 'topic_type' => POST_NORMAL, + 'topic_first_post_id' => (int) $row['topic_first_post_id'], + 'topic_first_poster_colour'=>(string) $row['topic_first_poster_colour'], + 'topic_first_poster_name'=> (string) $row['topic_first_poster_name'], + 'topic_last_post_id' => (int) $row['topic_last_post_id'], + 'topic_last_poster_id' => (int) $row['topic_last_poster_id'], + 'topic_last_poster_colour'=>(string) $row['topic_last_poster_colour'], + 'topic_last_poster_name'=> (string) $row['topic_last_poster_name'], + 'topic_last_post_subject'=> (string) $row['topic_last_post_subject'], + 'topic_last_post_time' => (int) $row['topic_last_post_time'], + 'topic_last_view_time' => (int) $row['topic_last_view_time'], + 'topic_moved_id' => (int) $row['topic_id'], + 'topic_bumped' => (int) $row['topic_bumped'], + 'topic_bumper' => (int) $row['topic_bumper'], + 'poll_title' => (string) $row['poll_title'], + 'poll_start' => (int) $row['poll_start'], + 'poll_length' => (int) $row['poll_length'], + 'poll_max_options' => (int) $row['poll_max_options'], + 'poll_last_vote' => (int) $row['poll_last_vote'] + ); + + $db->sql_query('INSERT INTO ' . TOPICS_TABLE . $db->sql_build_array('INSERT', $shadow)); + + $topics_authed_moved--; + $topics_moved--; + } + } + unset($topic_data); + + $sync_sql[$forum_id][] = 'forum_topics_real = forum_topics_real - ' . (int) $topics_moved; + + if ($topics_authed_moved) + { + $sync_sql[$forum_id][] = 'forum_topics = forum_topics - ' . (int) $topics_authed_moved; + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_MOVED_SUCCESS' : 'TOPICS_MOVED_SUCCESS'; + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + $db->sql_transaction('commit'); + + sync('forum', 'forum_id', array($forum_id, $to_forum_id)); + } + else + { + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select($to_forum_id, $forum_id, false, true, true, true), + 'S_CAN_LEAVE_SHADOW' => true, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'MOVE_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + + $message = $user->lang[$success_msg]; + $message .= '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>'); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid('viewforum', "f=$forum_id") . '">', '</a>'); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid('viewforum', "f=$to_forum_id") . '">', '</a>'); + + trigger_error($message); + } +} + +/** +* Delete Topics +*/ +function mcp_delete_topic($topic_ids) +{ + global $auth, $user, $db; + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_delete'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $forum_id = request_var('f', 0); + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'delete_topic', + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_DELETED_SUCCESS' : 'TOPICS_DELETED_SUCCESS'; + + $data = get_topic_data($topic_ids); + + foreach ($data as $topic_id => $row) + { + add_log('mod', $row['forum_id'], $topic_id, 'LOG_DELETE_' . ($row['topic_moved_id'] ? 'SHADOW_' : '') . 'TOPIC', $row['topic_title']); + } + + $return = delete_topics('topic_id', $topic_ids); + } + else + { + confirm_box(false, (sizeof($topic_ids) == 1) ? 'DELETE_TOPIC' : 'DELETE_TOPICS', $s_hidden_fields); + } + + if (!request::is_set('quickmod')) + { + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + $redirect_message = 'PAGE'; + } + else + { + $redirect = append_sid('viewforum', 'f=' . $forum_id); + $redirect_message = 'FORUM'; + } + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_' . $redirect_message], '<a href="' . $redirect . '">', '</a>')); + } +} + +/** +* Delete Posts +*/ +function mcp_delete_post($post_ids) +{ + global $auth, $user, $db; + + if (!check_ids($post_ids, POSTS_TABLE, 'post_id', array('m_delete'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $forum_id = request_var('f', 0); + + $s_hidden_fields = build_hidden_fields(array( + 'post_id_list' => $post_ids, + 'f' => $forum_id, + 'action' => 'delete_post', + 'redirect' => $redirect) + ); + $success_msg = ''; + + if (confirm_box(true)) + { + if (!function_exists('delete_posts')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); + } + + // Count the number of topics that are affected + // I did not use COUNT(DISTINCT ...) because I remember having problems + // with it on older versions of MySQL -- Ashe + + $sql = 'SELECT DISTINCT topic_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_id', $post_ids); + $result = $db->sql_query($sql); + + $topic_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id_list[] = $row['topic_id']; + } + $affected_topics = sizeof($topic_id_list); + $db->sql_freeresult($result); + + $post_data = get_post_data($post_ids); + + foreach ($post_data as $id => $row) + { + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_DELETE_POST', $row['post_subject']); + } + + // Now delete the posts, topics and forums are automatically resync'ed + delete_posts('post_id', $post_ids); + + $sql = 'SELECT COUNT(topic_id) AS topics_left + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topic_id_list); + $result = $db->sql_query_limit($sql, 1); + + $deleted_topics = ($row = $db->sql_fetchrow($result)) ? ($affected_topics - $row['topics_left']) : $affected_topics; + $db->sql_freeresult($result); + + $topic_id = request_var('t', 0); + + // Return links + $return_link = array(); + if ($affected_topics == 1 && !$deleted_topics && $topic_id) + { + $return_link[] = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', "f=$forum_id&t=$topic_id") . '">', '</a>'); + } + $return_link[] = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid('viewforum', 'f=' . $forum_id) . '">', '</a>'); + + if (sizeof($post_ids) == 1) + { + if ($deleted_topics) + { + // We deleted the only post of a topic, which in turn has + // been removed from the database + $success_msg = $user->lang['TOPIC_DELETED_SUCCESS']; + } + else + { + $success_msg = $user->lang['POST_DELETED_SUCCESS']; + } + } + else + { + if ($deleted_topics) + { + // Some of topics disappeared + $success_msg = $user->lang['POSTS_DELETED_SUCCESS'] . '<br /><br />' . $user->lang['EMPTY_TOPICS_REMOVED_WARNING']; + } + else + { + $success_msg = $user->lang['POSTS_DELETED_SUCCESS']; + } + } + } + else + { + confirm_box(false, (sizeof($post_ids) == 1) ? 'DELETE_POST' : 'DELETE_POSTS', $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + trigger_error($success_msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>') . '<br /><br />' . implode('<br /><br />', $return_link)); + } +} + +/** +* Fork Topic +*/ +function mcp_fork_topic($topic_ids) +{ + global $auth, $user, $db, $template, $config; + + if (!check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_'))) + { + return; + } + + $to_forum_id = request_var('to_forum_id', 0); + $forum_id = request_var('f', 0); + $redirect = request_var('redirect', build_url(array('action', 'quickmod'))); + $additional_msg = $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'topic_id_list' => $topic_ids, + 'f' => $forum_id, + 'action' => 'fork', + 'redirect' => $redirect) + ); + + if ($to_forum_id) + { + $forum_data = get_forum_data($to_forum_id, 'f_post'); + + if (!sizeof($topic_ids)) + { + $additional_msg = $user->lang['NO_TOPIC_SELECTED']; + } + else if (!sizeof($forum_data)) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + else + { + $forum_data = $forum_data[$to_forum_id]; + + if ($forum_data['forum_type'] != FORUM_POST) + { + $additional_msg = $user->lang['FORUM_NOT_POSTABLE']; + } + else if (!$auth->acl_get('f_post', $to_forum_id)) + { + $additional_msg = $user->lang['USER_CANNOT_POST']; + } + } + } + else if (request::is_set_post('confirm')) + { + $additional_msg = $user->lang['FORUM_NOT_EXIST']; + } + + if (!$additional_msg && confirm_box(true)) + { + $topic_data = get_topic_data($topic_ids, 'f_post'); + + $total_posts = 0; + $new_topic_id_list = array(); + + foreach ($topic_data as $topic_id => $topic_row) + { + $sql_ary = array( + 'forum_id' => (int) $to_forum_id, + 'icon_id' => (int) $topic_row['icon_id'], + 'topic_attachment' => (int) $topic_row['topic_attachment'], + 'topic_approved' => 1, + 'topic_reported' => 0, + 'topic_title' => (string) $topic_row['topic_title'], + 'topic_poster' => (int) $topic_row['topic_poster'], + 'topic_time' => (int) $topic_row['topic_time'], + 'topic_replies' => (int) $topic_row['topic_replies_real'], + 'topic_replies_real' => (int) $topic_row['topic_replies_real'], + 'topic_status' => (int) $topic_row['topic_status'], + 'topic_type' => (int) $topic_row['topic_type'], + 'topic_first_poster_name' => (string) $topic_row['topic_first_poster_name'], + 'topic_last_poster_id' => (int) $topic_row['topic_last_poster_id'], + 'topic_last_poster_name' => (string) $topic_row['topic_last_poster_name'], + 'topic_last_post_time' => (int) $topic_row['topic_last_post_time'], + 'topic_last_view_time' => (int) $topic_row['topic_last_view_time'], + 'topic_bumped' => (int) $topic_row['topic_bumped'], + 'topic_bumper' => (int) $topic_row['topic_bumper'], + 'poll_title' => (string) $topic_row['poll_title'], + 'poll_start' => (int) $topic_row['poll_start'], + 'poll_length' => (int) $topic_row['poll_length'] + ); + + $db->sql_query('INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $new_topic_id = $db->sql_nextid(); + $new_topic_id_list[$topic_id] = $new_topic_id; + + if ($topic_row['poll_start']) + { + $poll_rows = array(); + + $sql = 'SELECT * + FROM ' . POLL_OPTIONS_TABLE . " + WHERE topic_id = $topic_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary = array( + 'poll_option_id' => (int) $row['poll_option_id'], + 'topic_id' => (int) $new_topic_id, + 'poll_option_text' => (string) $row['poll_option_text'], + 'poll_option_total' => 0 + ); + + $db->sql_query('INSERT INTO ' . POLL_OPTIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + } + } + + $sql = 'SELECT * + FROM ' . POSTS_TABLE . " + WHERE topic_id = $topic_id + ORDER BY post_time ASC"; + $result = $db->sql_query($sql); + + $post_rows = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_rows[] = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($post_rows)) + { + continue; + } + + $total_posts += sizeof($post_rows); + foreach ($post_rows as $row) + { + $sql_ary = array( + 'topic_id' => (int) $new_topic_id, + 'forum_id' => (int) $to_forum_id, + 'poster_id' => (int) $row['poster_id'], + 'icon_id' => (int) $row['icon_id'], + 'poster_ip' => (string) $row['poster_ip'], + 'post_time' => (int) $row['post_time'], + 'post_approved' => 1, + 'post_reported' => 0, + 'enable_bbcode' => (int) $row['enable_bbcode'], + 'enable_smilies' => (int) $row['enable_smilies'], + 'enable_magic_url' => (int) $row['enable_magic_url'], + 'enable_sig' => (int) $row['enable_sig'], + 'post_username' => (string) $row['post_username'], + 'post_subject' => (string) $row['post_subject'], + 'post_text' => (string) $row['post_text'], + 'post_edit_reason' => (string) $row['post_edit_reason'], + 'post_edit_user' => (int) $row['post_edit_user'], + 'post_checksum' => (string) $row['post_checksum'], + 'post_attachment' => (int) $row['post_attachment'], + 'bbcode_bitfield' => $row['bbcode_bitfield'], + 'bbcode_uid' => (string) $row['bbcode_uid'], + 'post_edit_time' => (int) $row['post_edit_time'], + 'post_edit_count' => (int) $row['post_edit_count'], + 'post_edit_locked' => (int) $row['post_edit_locked'], + 'post_postcount' => 0, + ); + + $db->sql_query('INSERT INTO ' . POSTS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + $new_post_id = $db->sql_nextid(); + + // Copy whether the topic is dotted + markread('post', $to_forum_id, $new_topic_id, 0, $row['poster_id']); + + // Copy Attachments + if ($row['post_attachment']) + { + $sql = 'SELECT * FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = {$row['post_id']} + AND topic_id = $topic_id + AND in_message = 0"; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($attach_row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'post_msg_id' => (int) $new_post_id, + 'topic_id' => (int) $new_topic_id, + 'in_message' => 0, + 'is_orphan' => (int) $attach_row['is_orphan'], + 'poster_id' => (int) $attach_row['poster_id'], + 'physical_filename' => (string) basename($attach_row['physical_filename']), + 'real_filename' => (string) basename($attach_row['real_filename']), + 'download_count' => (int) $attach_row['download_count'], + 'attach_comment' => (string) $attach_row['attach_comment'], + 'extension' => (string) $attach_row['extension'], + 'mimetype' => (string) $attach_row['mimetype'], + 'filesize' => (int) $attach_row['filesize'], + 'filetime' => (int) $attach_row['filetime'], + 'thumbnail' => (int) $attach_row['thumbnail'] + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(ATTACHMENTS_TABLE, $sql_ary); + } + } + } + + $sql = 'SELECT user_id, notify_status + FROM ' . TOPICS_WATCH_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query($sql); + + $sql_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + $sql_ary[] = array( + 'topic_id' => (int) $new_topic_id, + 'user_id' => (int) $row['user_id'], + 'notify_status' => (int) $row['notify_status'], + ); + } + $db->sql_freeresult($result); + + if (sizeof($sql_ary)) + { + $db->sql_multi_insert(TOPICS_WATCH_TABLE, $sql_ary); + } + } + + // Sync new topics, parent forums and board stats + sync('topic', 'topic_id', $new_topic_id_list); + + $sync_sql = array(); + + $sync_sql[$to_forum_id][] = 'forum_posts = forum_posts + ' . $total_posts; + $sync_sql[$to_forum_id][] = 'forum_topics = forum_topics + ' . sizeof($new_topic_id_list); + $sync_sql[$to_forum_id][] = 'forum_topics_real = forum_topics_real + ' . sizeof($new_topic_id_list); + + foreach ($sync_sql as $forum_id_key => $array) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET ' . implode(', ', $array) . ' + WHERE forum_id = ' . $forum_id_key; + $db->sql_query($sql); + } + + sync('forum', 'forum_id', $to_forum_id); + set_config('num_topics', $config['num_topics'] + sizeof($new_topic_id_list), true); + set_config('num_posts', $config['num_posts'] + $total_posts, true); + + foreach ($new_topic_id_list as $topic_id => $new_topic_id) + { + add_log('mod', $to_forum_id, $new_topic_id, 'LOG_FORK', $topic_row['forum_name']); + } + + $success_msg = (sizeof($topic_ids) == 1) ? 'TOPIC_FORKED_SUCCESS' : 'TOPICS_FORKED_SUCCESS'; + } + else + { + $template->assign_vars(array( + 'S_FORUM_SELECT' => make_forum_select($to_forum_id, false, false, true, true, true), + 'S_CAN_LEAVE_SHADOW' => false, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'FORK_TOPIC' . ((sizeof($topic_ids) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_move.html'); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + $redirect_url = append_sid('viewforum', 'f=' . $forum_id); + meta_refresh(3, $redirect_url); + $return_link = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect_url . '">', '</a>'); + + if ($forum_id != $to_forum_id) + { + $return_link .= '<br /><br />' . sprintf($user->lang['RETURN_NEW_FORUM'], '<a href="' . append_sid('viewforum', 'f=' . $to_forum_id) . '">', '</a>'); + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_notes.php b/phpBB/modules/mcp/mcp_notes.php new file mode 100644 index 0000000000..5ca3d8f606 --- /dev/null +++ b/phpBB/modules/mcp/mcp_notes.php @@ -0,0 +1,242 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_notes +* Displays notes about a user +* @package mcp +*/ +class mcp_notes +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $config; + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + + $this->page_title = 'MCP_NOTES'; + + switch ($mode) + { + case 'front': + $template->assign_vars(array( + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=mcp&field=username&select_single=true'), + 'U_POST_ACTION' => append_sid('mcp', 'i=notes&mode=user_notes'), + + 'L_TITLE' => $user->lang['MCP_NOTES'], + )); + + $this->tpl_name = 'mcp_notes_front'; + break; + + case 'user_notes': + $user->add_lang('acp/common'); + + $this->mcp_notes_user_view($action); + $this->tpl_name = 'mcp_notes_user'; + break; + } + } + + /** + * Display user notes + */ + function mcp_notes_user_view($action) + { + global $template, $db, $user, $auth, $config; + + $user_id = request_var('u', 0); + $username = request_var('username', '', true); + $start = request_var('start', 0); + $st = request_var('st', 0); + $sk = request_var('sk', 'b'); + $sd = request_var('sd', 'd'); + + add_form_key('mcp_notes'); + + $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . " + WHERE $sql_where"; + $result = $db->sql_query($sql); + $userrow = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$userrow) + { + trigger_error('NO_USER'); + } + + $user_id = $userrow['user_id']; + + // Populate user id to the currently active module (this module) + // The following method is another way of adjusting module urls. It is the easy variant if we want + // to directly adjust the current module url based on data retrieved within the same module. + if (strpos($this->u_action, "&u=$user_id") === false) + { + $this->p_master->adjust_url('&u=' . $user_id); + $this->u_action .= "&u=$user_id"; + } + + $deletemark = ($action == 'del_marked') ? true : false; + $deleteall = ($action == 'del_all') ? true : false; + $marked = request_var('marknote', array(0)); + $usernote = utf8_normalize_nfc(request_var('usernote', '', true)); + + // Handle any actions + if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs')) + { + $where_sql = ''; + if ($deletemark && $marked) + { + $sql_in = array(); + foreach ($marked as $mark) + { + $sql_in[] = $mark; + } + $where_sql = ' AND ' . $db->sql_in_set('log_id', $sql_in); + unset($sql_in); + } + + if ($where_sql || $deleteall) + { + if (check_form_key('mcp_notes')) + { + $sql = 'DELETE FROM ' . LOG_TABLE . ' + WHERE log_type = ' . LOG_USERS . " + AND reportee_id = $user_id + $where_sql"; + $db->sql_query($sql); + + add_log('admin', 'LOG_CLEAR_USER', $userrow['username']); + + $msg = ($deletemark) ? 'MARKED_NOTES_DELETED' : 'ALL_NOTES_DELETED'; + } + else + { + $msg = 'FORM_INVALID'; + } + $redirect = $this->u_action . '&u=' . $user_id; + meta_refresh(3, $redirect); + trigger_error($user->lang[$msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + } + + if ($usernote && $action == 'add_feedback') + { + if (check_form_key('mcp_notes')) + { + add_log('admin', 'LOG_USER_FEEDBACK', $userrow['username']); + add_log('mod', 0, 0, 'LOG_USER_FEEDBACK', $userrow['username']); + + add_log('user', $user_id, 'LOG_USER_GENERAL', $usernote); + $msg = $user->lang['USER_FEEDBACK_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = $this->u_action; + meta_refresh(3, $redirect); + + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($userrow['user_avatar'], $userrow['user_avatar_type'], $userrow['user_avatar_width'], $userrow['user_avatar_height']); + + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_IP'], 'd' => $user->lang['SORT_ACTION']); + $sort_by_sql = array('a' => 'u.username_clean', 'b' => 'l.log_time', 'c' => 'l.log_ip', 'd' => 'l.log_operation'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $st, $sk, $sd, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($st) ? (time() - ($st * 86400)) : 0; + $sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC'); + + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['posts_per_page'], $start, 0, 0, $user_id, $sql_where, $sql_sort); + + if ($log_count) + { + $template->assign_var('S_USER_NOTES', true); + + foreach ($log_data as $row) + { + $template->assign_block_vars('usernotes', array( + 'REPORT_BY' => $row['username_full'], + 'REPORT_AT' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'IP' => $row['ip'], + 'ID' => $row['id']) + ); + } + } + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + + 'L_TITLE' => $user->lang['MCP_NOTES_USER'], + + 'PAGE_NUMBER' => on_page($log_count, $config['posts_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&st=$st&sk=$sk&sd=$sd", $log_count, $config['posts_per_page'], $start), + 'TOTAL_REPORTS' => ($log_count == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $log_count), + + 'USERNAME' => $userrow['username'], + 'USER_COLOR' => (!empty($userrow['user_colour'])) ? $userrow['user_colour'] : '', + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($userrow['user_regdate']), + 'POSTS' => ($userrow['user_posts']) ? $userrow['user_posts'] : 0, + 'WARNINGS' => ($userrow['user_warnings']) ? $userrow['user_warnings'] : 0, + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + ) + ); + } + +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_post.php b/phpBB/modules/mcp/mcp_post.php new file mode 100644 index 0000000000..5717242541 --- /dev/null +++ b/phpBB/modules/mcp/mcp_post.php @@ -0,0 +1,501 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Handling actions in post details screen +*/ +function mcp_post_details($id, $mode, $action) +{ + global $template, $db, $user, $auth, $cache, $config; + + $user->add_lang('posting'); + + $post_id = request_var('p', 0); + $start = request_var('start', 0); + + // Get post data + $post_info = get_post_data(array($post_id), false, true); + + add_form_key('mcp_post_details'); + + if (!sizeof($post_info)) + { + trigger_error('POST_NOT_EXIST'); + } + + $post_info = $post_info[$post_id]; + $extra_url = extra_url(); + $url = ($extra_url) ? append_sid('mcp', extra_url()) : append_sid('mcp') . '?'; + + switch ($action) + { + case 'whois': + + if ($auth->acl_get('m_info', $post_info['forum_id'])) + { + $ip = request_var('ip', ''); + include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + $template->assign_vars(array( + 'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . append_sid('mcp', "i=$id&mode=$mode&p=$post_id") . '">', '</a>'), + 'U_RETURN_POST' => append_sid('mcp', "i=$id&mode=$mode&p=$post_id"), + 'L_RETURN_POST' => sprintf($user->lang['RETURN_POST'], '', ''), + 'WHOIS' => user_ipwhois($ip), + )); + } + + // We're done with the whois page so return + return; + + break; + + case 'chgposter': + case 'chgposter_ip': + + if ($action == 'chgposter') + { + $username = request_var('username', '', true); + $sql_where = "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + } + else + { + $new_user_id = request_var('u', 0); + $sql_where = 'user_id = ' . $new_user_id; + } + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE ' . $sql_where; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_USER'); + } + + if ($auth->acl_get('m_chgposter', $post_info['forum_id'])) + { + if (check_form_key('mcp_post_details')) + { + change_poster($post_info, $row); + } + else + { + trigger_error('FORM_INVALID'); + } + } + + break; + } + + // Set some vars + $users_ary = $usernames_ary = array(); + $attachments = $extensions = array(); + $post_id = $post_info['post_id']; + $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $extensions = cache::obtain_attach_extensions($post_info['forum_id']); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $template->assign_vars(array( + 'U_MCP_ACTION' => "$url&i=main&quickmod=1", // Use this for mode paramaters + 'U_POST_ACTION' => "$url&i=$id&mode=post_details", // Use this for action parameters + 'U_APPROVE_ACTION' => append_sid('mcp', "i=queue&p=$post_id&f={$post_info['forum_id']}"), + + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_CAN_CHGPOSTER' => $auth->acl_get('m_chgposter', $post_info['forum_id']), + 'S_CAN_LOCK_POST' => $auth->acl_get('m_lock', $post_info['forum_id']), + 'S_CAN_DELETE_POST' => $auth->acl_get('m_delete', $post_info['forum_id']), + + 'S_POST_REPORTED' => ($post_info['post_reported']) ? true : false, + 'S_POST_UNAPPROVED' => (!$post_info['post_approved']) ? true : false, + 'S_POST_LOCKED' => ($post_info['post_edit_locked']) ? true : false, + 'S_USER_NOTES' => true, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid('posting', "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=mcp_chgposter&field=username&select_single=true'), + 'U_MCP_APPROVE' => append_sid('mcp', 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid('mcp', 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_USER_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid('mcp', 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), + 'U_VIEW_TOPIC' => append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', "f={$post_info['forum_id']}&p=$post_id") . "#p$post_id\">", '</a>'), + 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid('viewforum', "f={$post_info['forum_id']}&start={$start}") . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'SEARCH_IMG' => $user->img('icon_user_search', $user->lang['SEARCH']), + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => $post_info['post_subject'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? "$url&i=$id&mode=$mode&lookup={$post_info['poster_ip']}#ip" : '', + 'U_WHOIS' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid('mcp', "i=$id&mode=$mode&action=whois&p=$post_id&ip={$post_info['poster_ip']}") : '', + )); + + // Get User Notes + $log_data = array(); + $log_count = 0; + view_log('user', $log_data, $log_count, $config['posts_per_page'], 0, 0, 0, $post_info['user_id']); + + if ($log_count) + { + $template->assign_var('S_USER_NOTES', true); + + foreach ($log_data as $row) + { + $template->assign_block_vars('usernotes', array( + 'REPORT_BY' => $row['username_full'], + 'REPORT_AT' => $user->format_date($row['time']), + 'ACTION' => $row['action'], + 'ID' => $row['id']) + ); + } + } + + // Get Reports + if ($auth->acl_get('m_', $post_info['forum_id'])) + { + $sql = 'SELECT r.*, re.*, u.user_id, u.username + FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u, ' . REPORTS_REASONS_TABLE . " re + WHERE r.post_id = $post_id + AND r.reason_id = re.reason_id + AND u.user_id = r.user_id + ORDER BY r.report_time DESC"; + $result = $db->sql_query($sql); + + if ($row = $db->sql_fetchrow($result)) + { + $template->assign_var('S_SHOW_REPORTS', true); + + do + { + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $row['reson_description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; + $row['reason_title'] = $user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; + } + + $template->assign_block_vars('reports', array( + 'REPORT_ID' => $row['report_id'], + 'REASON_TITLE' => $row['reason_title'], + 'REASON_DESC' => $row['reason_description'], + 'REPORTER' => ($row['user_id'] != ANONYMOUS) ? $row['username'] : $user->lang['GUEST'], + 'U_REPORTER' => ($row['user_id'] != ANONYMOUS) ? append_sid('memberlist', 'mode=viewprofile&u=' . $row['user_id']) : '', + 'USER_NOTIFY' => ($row['user_notify']) ? true : false, + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'REPORT_TEXT' => bbcode_nl2br(trim($row['report_text'])), + )); + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + } + + // Get IP + if ($auth->acl_get('m_info', $post_info['forum_id'])) + { + $rdns_ip_num = request_var('rdns', ''); + + if ($rdns_ip_num != 'all') + { + $template->assign_vars(array( + 'U_LOOKUP_ALL' => "$url&i=main&mode=post_details&rdns=all") + ); + } + + // Get other users who've posted under this IP + $sql = 'SELECT poster_id, COUNT(poster_id) as postings + FROM ' . POSTS_TABLE . " + WHERE poster_ip = '" . $db->sql_escape($post_info['poster_ip']) . "' + GROUP BY poster_id + ORDER BY postings DESC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + // Fill the user select list with users who have posted under this IP + if ($row['poster_id'] != $post_info['poster_id']) + { + $users_ary[$row['poster_id']] = $row; + } + } + $db->sql_freeresult($result); + + if (sizeof($users_ary)) + { + // Get the usernames + $sql = 'SELECT user_id, username + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($users_ary)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $users_ary[$row['user_id']]['username'] = $row['username']; + $usernames_ary[utf8_clean_string($row['username'])] = $users_ary[$row['user_id']]; + } + $db->sql_freeresult($result); + + foreach ($users_ary as $user_id => $user_row) + { + $template->assign_block_vars('userrow', array( + 'USERNAME' => ($user_id == ANONYMOUS) ? $user->lang['GUEST'] : $user_row['username'], + 'NUM_POSTS' => $user_row['postings'], + 'L_POST_S' => ($user_row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'], + + 'U_PROFILE' => ($user_id == ANONYMOUS) ? '' : append_sid('memberlist', 'mode=viewprofile&u=' . $user_id), + 'U_SEARCHPOSTS' => append_sid('search', 'author_id=' . $user_id . '&sr=topics')) + ); + } + } + + // Get other IP's this user has posted under + + // A compound index on poster_id, poster_ip (posts table) would help speed up this query a lot, + // but the extra size is only valuable if there are persons having more than a thousands posts. + // This is better left to the really really big forums. + + $sql = 'SELECT poster_ip, COUNT(poster_ip) AS postings + FROM ' . POSTS_TABLE . ' + WHERE poster_id = ' . $post_info['poster_id'] . " + GROUP BY poster_ip + ORDER BY postings DESC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $hostname = (($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') && $row['poster_ip']) ? @gethostbyaddr($row['poster_ip']) : ''; + + $template->assign_block_vars('iprow', array( + 'IP' => $row['poster_ip'], + 'HOSTNAME' => $hostname, + 'NUM_POSTS' => $row['postings'], + 'L_POST_S' => ($row['postings'] == 1) ? $user->lang['POST'] : $user->lang['POSTS'], + + 'U_LOOKUP_IP' => ($rdns_ip_num == $row['poster_ip'] || $rdns_ip_num == 'all') ? '' : "$url&i=$id&mode=post_details&rdns={$row['poster_ip']}#ip", + 'U_WHOIS' => append_sid('mcp', "i=$id&mode=$mode&action=whois&p=$post_id&ip={$row['poster_ip']}")) + ); + } + $db->sql_freeresult($result); + + $user_select = ''; + + if (sizeof($usernames_ary)) + { + ksort($usernames_ary); + + foreach ($usernames_ary as $row) + { + $user_select .= '<option value="' . $row['poster_id'] . '">' . $row['username'] . "</option>\n"; + } + } + + $template->assign_var('S_USER_SELECT', $user_select); + } + +} + +/** +* Change a post's poster +*/ +function change_poster(&$post_info, $userdata) +{ + global $auth, $db, $config; + + if (empty($userdata) || $userdata['user_id'] == $post_info['user_id']) + { + return; + } + + $post_id = $post_info['post_id']; + + $sql = 'UPDATE ' . POSTS_TABLE . " + SET poster_id = {$userdata['user_id']} + WHERE post_id = $post_id"; + $db->sql_query($sql); + + // Resync topic/forum if needed + if ($post_info['topic_last_post_id'] == $post_id || $post_info['forum_last_post_id'] == $post_id || $post_info['topic_first_post_id'] == $post_id) + { + sync('topic', 'topic_id', $post_info['topic_id'], false, false); + sync('forum', 'forum_id', $post_info['forum_id'], false, false); + } + + // Adjust post counts... only if the post is approved (else, it was not added the users post count anyway) + if ($post_info['post_postcount'] && $post_info['post_approved']) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts - 1 + WHERE user_id = ' . $post_info['user_id'] .' + AND user_posts > 0'; + $db->sql_query($sql); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + 1 + WHERE user_id = ' . $userdata['user_id']; + $db->sql_query($sql); + } + + // Add posted to information for this topic for the new user + markread('post', $post_info['forum_id'], $post_info['topic_id'], time(), $userdata['user_id']); + + // Remove the dotted topic option if the old user has no more posts within this topic + if ($config['load_db_track'] && $post_info['user_id'] != ANONYMOUS) + { + $sql = 'SELECT topic_id + FROM ' . POSTS_TABLE . ' + WHERE topic_id = ' . $post_info['topic_id'] . ' + AND poster_id = ' . $post_info['user_id']; + $result = $db->sql_query_limit($sql, 1); + $topic_id = (int) $db->sql_fetchfield('topic_id'); + $db->sql_freeresult($result); + + if (!$topic_id) + { + $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' + WHERE user_id = ' . $post_info['user_id'] . ' + AND topic_id = ' . $post_info['topic_id']; + $db->sql_query($sql); + } + } + + // change the poster_id within the attachments table, else the data becomes out of sync and errors displayed because of wrong ownership + if ($post_info['post_attachment']) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET poster_id = ' . $userdata['user_id'] . ' + WHERE poster_id = ' . $post_info['user_id'] . ' + AND post_msg_id = ' . $post_info['post_id'] . ' + AND topic_id = ' . $post_info['topic_id']; + $db->sql_query($sql); + } + + // refresh search cache of this post + $search_type = basename($config['search_type']); + + if (file_exists(PHPBB_ROOT_PATH . 'includes/search/' . $search_type . '.' . PHP_EXT)) + { + require(PHPBB_ROOT_PATH . "includes/search/$search_type." . PHP_EXT); + + // We do some additional checks in the module to ensure it can actually be utilised + $error = false; + $search = new $search_type($error); + + if (!$error && method_exists($search, 'destroy_cache')) + { + $search->destroy_cache(array(), array($post_info['user_id'], $userdata['user_id'])); + } + } + + $from_username = $post_info['username']; + $to_username = $userdata['username']; + + // Renew post info + $post_info = get_post_data(array($post_id), false, true); + + if (!sizeof($post_info)) + { + trigger_error('POST_NOT_EXIST'); + } + + $post_info = $post_info[$post_id]; + + // Now add log entry + add_log('mod', $post_info['forum_id'], $post_info['topic_id'], 'LOG_MCP_CHANGE_POSTER', $post_info['topic_title'], $from_username, $to_username); +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_queue.php b/phpBB/modules/mcp/mcp_queue.php new file mode 100644 index 0000000000..0db75dd268 --- /dev/null +++ b/phpBB/modules/mcp/mcp_queue.php @@ -0,0 +1,1072 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_queue +* Handling the moderation queue +* @package mcp +*/ +class mcp_queue +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $cache; + global $config, $action; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + + $forum_id = request_var('f', 0); + $start = request_var('start', 0); + + $this->page_title = 'MCP_QUEUE'; + + switch ($action) + { + case 'approve': + case 'disapprove': + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $post_id_list = request_var('post_id_list', array(0)); + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + if ($action == 'approve') + { + approve_post($post_id_list, 'queue', $mode); + } + else + { + disapprove_post($post_id_list, 'queue', $mode); + } + + break; + } + + switch ($mode) + { + case 'approve_details': + + $this->tpl_name = 'mcp_post'; + + $user->add_lang(array('posting', 'viewtopic')); + + $post_id = request_var('p', 0); + $topic_id = request_var('t', 0); + + if ($topic_id) + { + $topic_info = get_topic_data(array($topic_id), 'm_approve'); + if (isset($topic_info[$topic_id]['topic_first_post_id'])) + { + $post_id = (int) $topic_info[$topic_id]['topic_first_post_id']; + } + else + { + $topic_id = 0; + } + } + + $post_info = get_post_data(array($post_id), 'm_approve', true); + + if (!sizeof($post_info)) + { + trigger_error('NO_POST_SELECTED'); + } + + $post_info = $post_info[$post_id]; + + if ($post_info['topic_first_post_id'] != $post_id && topic_review($post_info['topic_id'], $post_info['forum_id'], 'topic_review', 0, false)) + { + $template->assign_vars(array( + 'S_TOPIC_REVIEW' => true, + 'TOPIC_TITLE' => $post_info['topic_title']) + ); + } + + $extensions = $attachments = $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $extensions = cache::obtain_attach_extensions($post_info['forum_id']); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $post_url = append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']); + $topic_url = append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']); + + $template->assign_vars(array( + 'S_MCP_QUEUE' => true, + 'U_APPROVE_ACTION' => append_sid('mcp', "i=queue&p=$post_id&f=$forum_id"), + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_POST_REPORTED' => $post_info['post_reported'], + 'S_POST_UNAPPROVED' => !$post_info['post_approved'], + 'S_POST_LOCKED' => $post_info['post_edit_locked'], + 'S_USER_NOTES' => true, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid('posting', "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_MCP_APPROVE' => append_sid('mcp', 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid('mcp', 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_USER_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid('mcp', 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_POST' => $post_url, + 'U_VIEW_TOPIC' => $topic_url, + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'RETURN_QUEUE' => sprintf($user->lang['RETURN_QUEUE'], '<a href="' . append_sid('mcp', 'i=queue' . (($topic_id) ? '&mode=unapproved_topics' : '&mode=unapproved_posts')) . "&start=$start\">", '</a>'), + 'RETURN_POST' => sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'), + 'RETURN_TOPIC_SIMPLE' => sprintf($user->lang['RETURN_TOPIC_SIMPLE'], '<a href="' . $topic_url . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => $post_info['post_subject'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? append_sid('mcp', 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id . '&lookup=' . $post_info['poster_ip']) . '#ip' : '', + )); + + break; + + case 'unapproved_topics': + case 'unapproved_posts': + $user->add_lang(array('viewtopic', 'viewforum')); + + $topic_id = request_var('t', 0); + $forum_info = array(); + + if ($topic_id) + { + $topic_info = get_topic_data(array($topic_id)); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + $topic_info = $topic_info[$topic_id]; + $forum_id = $topic_info['forum_id']; + } + + $forum_list_approve = get_forum_list('m_approve', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_approve as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_approve[$k]); + } + } + unset($forum_list_read); + + if (!$forum_id) + { + $forum_list = array(); + foreach ($forum_list_approve as $row) + { + $forum_list[] = $row['forum_id']; + } + + if (!sizeof($forum_list)) + { + trigger_error('NOT_MODERATOR'); + } + + $global_id = $forum_list[0]; + + $forum_list = implode(', ', $forum_list); + + $sql = 'SELECT SUM(forum_topics) as sum_forum_topics + FROM ' . FORUMS_TABLE . " + WHERE forum_id IN (0, $forum_list)"; + $result = $db->sql_query($sql); + $forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); + $db->sql_freeresult($result); + } + else + { + $forum_info = get_forum_data(array($forum_id), 'm_approve'); + + if (!sizeof($forum_info)) + { + trigger_error('NOT_MODERATOR'); + } + + $forum_info = $forum_info[$forum_id]; + $forum_list = $forum_id; + $global_id = $forum_id; + } + + $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; + foreach ($forum_list_approve as $row) + { + $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . $row['forum_name'] . '</option>'; + } + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + $forum_names = array(); + + if ($mode == 'unapproved_posts') + { + $sql = 'SELECT p.post_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . " + WHERE p.forum_id IN (0, $forum_list) + AND p.post_approved = 0 + " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . ' + ' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . " + AND t.topic_id = p.topic_id + AND t.topic_first_post_id <> p.post_id + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $i = 0; + $post_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_ids[] = $row['post_id']; + $row_num[$row['post_id']] = $i++; + } + $db->sql_freeresult($result); + + if (sizeof($post_ids)) + { + $sql = 'SELECT t.topic_id, t.topic_title, t.forum_id, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('p.post_id', $post_ids) . ' + AND t.topic_id = p.topic_id + AND u.user_id = p.poster_id + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query($sql); + + $post_data = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_id']) + { + $forum_names[] = $row['forum_id']; + } + $post_data[$row['post_id']] = $row; + } + $db->sql_freeresult($result); + + foreach ($post_ids as $post_id) + { + $rowset[] = $post_data[$post_id]; + } + unset($post_data, $post_ids); + } + else + { + $rowset = array(); + } + } + else + { + $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, t.topic_title AS post_subject, t.topic_time AS post_time, t.topic_poster AS poster_id, t.topic_first_post_id AS post_id, t.topic_first_poster_name AS username, t.topic_first_poster_colour AS user_colour + FROM ' . TOPICS_TABLE . " t + WHERE forum_id IN (0, $forum_list) + AND topic_approved = 0 + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['forum_id']) + { + $forum_names[] = $row['forum_id']; + } + $rowset[] = $row; + } + $db->sql_freeresult($result); + } + + if (sizeof($forum_names)) + { + // Select the names for the forum_ids + $sql = 'SELECT forum_id, forum_name + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_names); + $result = $db->sql_query($sql, 3600); + + $forum_names = array(); + while ($row = $db->sql_fetchrow($result)) + { + $forum_names[$row['forum_id']] = $row['forum_name']; + } + $db->sql_freeresult($result); + } + + foreach ($rowset as $row) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + if (empty($row['post_username'])) + { + $row['post_username'] = $user->lang['GUEST']; + } + + $template->assign_block_vars('postrow', array( + 'U_TOPIC' => append_sid('viewtopic', 'f=' . $row['forum_id'] . '&t=' . $row['topic_id']), + 'U_VIEWFORUM' => (!$global_topic) ? append_sid('viewforum', 'f=' . $row['forum_id']) : '', + 'U_VIEWPOST' => append_sid('viewtopic', 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . (($mode == 'unapproved_posts') ? '#p' . $row['post_id'] : ''), + 'U_VIEW_DETAILS' => append_sid('mcp', "i=queue&start=$start&mode=approve_details&f={$row['forum_id']}&p={$row['post_id']}" . (($mode == 'unapproved_topics') ? "&t={$row['topic_id']}" : '')), + + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'POST_ID' => $row['post_id'], + 'FORUM_NAME' => (!$global_topic) ? $forum_names[$row['forum_id']] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_SUBJECT' => $row['post_subject'], + 'TOPIC_TITLE' => $row['topic_title'], + 'POST_TIME' => $user->format_date($row['post_time'])) + ); + } + unset($rowset, $forum_names); + + // Now display the page + $template->assign_vars(array( + 'L_DISPLAY_ITEMS' => ($mode == 'unapproved_posts') ? $user->lang['DISPLAY_POSTS'] : $user->lang['DISPLAY_TOPICS'], + 'L_EXPLAIN' => ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS_EXPLAIN'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS_EXPLAIN'], + 'L_TITLE' => ($mode == 'unapproved_posts') ? $user->lang['MCP_QUEUE_UNAPPROVED_POSTS'] : $user->lang['MCP_QUEUE_UNAPPROVED_TOPICS'], + 'L_ONLY_TOPIC' => ($topic_id) ? sprintf($user->lang['ONLY_TOPIC'], $topic_info['topic_title']) : '', + + 'S_FORUM_OPTIONS' => $forum_options, + 'S_MCP_ACTION' => build_url(array('t', 'f', 'sd', 'st', 'sk')), + 'S_TOPICS' => ($mode == 'unapproved_posts') ? false : true, + + 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), + 'TOPIC_ID' => $topic_id, + 'TOTAL' => ($total == 1) ? (($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POST'] : $user->lang['VIEW_FORUM_TOPIC']) : sprintf((($mode == 'unapproved_posts') ? $user->lang['VIEW_TOPIC_POSTS'] : $user->lang['VIEW_FORUM_TOPICS']), $total), + )); + + $this->tpl_name = 'mcp_queue'; + break; + } + } +} + +/** +* Approve Post/Topic +*/ +function approve_post($post_id_list, $id, $mode) +{ + global $db, $template, $user, $config; + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + { + trigger_error('NOT_AUTHORISED'); + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + $success_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'post_id_list' => $post_id_list, + 'action' => 'approve', + 'redirect' => $redirect) + ); + + $post_info = get_post_data($post_id_list, 'm_approve'); + + if (confirm_box(true)) + { + $notify_poster = request::is_set('notify_poster'); + + // If Topic -> total_topics = total_topics+1, total_posts = total_posts+1, forum_topics = forum_topics+1, forum_posts = forum_posts+1 + // If Post -> total_posts = total_posts+1, forum_posts = forum_posts+1, topic_replies = topic_replies+1 + + $total_topics = $total_posts = 0; + $forum_topics_posts = $topic_approve_sql = $topic_replies_sql = $post_approve_sql = $topic_id_list = $forum_id_list = $approve_log = array(); + $user_posts_sql = array(); + + $update_forum_information = false; + + foreach ($post_info as $post_id => $post_data) + { + $topic_id_list[$post_data['topic_id']] = 1; + + if ($post_data['forum_id']) + { + $forum_id_list[$post_data['forum_id']] = 1; + } + + // User post update (we do not care about topic or post, since user posts are strictly connected to posts) + // But we care about forums where post counts get not increased. ;) + if ($post_data['post_postcount']) + { + $user_posts_sql[$post_data['poster_id']] = (empty($user_posts_sql[$post_data['poster_id']])) ? 1 : $user_posts_sql[$post_data['poster_id']] + 1; + } + + // Topic or Post. ;) + if ($post_data['topic_first_post_id'] == $post_id) + { + if ($post_data['forum_id']) + { + if (!isset($forum_topics_posts[$post_data['forum_id']])) + { + $forum_topics_posts[$post_data['forum_id']] = array( + 'forum_posts' => 0, + 'forum_topics' => 0 + ); + } + + $total_topics++; + $forum_topics_posts[$post_data['forum_id']]['forum_topics']++; + } + $topic_approve_sql[] = $post_data['topic_id']; + + $approve_log[] = array( + 'type' => 'topic', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => $post_data['topic_id'], + ); + } + else + { + if (!isset($topic_replies_sql[$post_data['topic_id']])) + { + $topic_replies_sql[$post_data['topic_id']] = 0; + } + $topic_replies_sql[$post_data['topic_id']]++; + + $approve_log[] = array( + 'type' => 'post', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => $post_data['topic_id'], + ); + } + + if ($post_data['forum_id']) + { + if (!isset($forum_topics_posts[$post_data['forum_id']])) + { + $forum_topics_posts[$post_data['forum_id']] = array( + 'forum_posts' => 0, + 'forum_topics' => 0 + ); + } + + $total_posts++; + $forum_topics_posts[$post_data['forum_id']]['forum_posts']++; + + // Increment by topic_replies if we approve a topic... + // This works because we do not adjust the topic_replies when re-approving a topic after an edit. + if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_replies']) + { + $total_posts += $post_data['topic_replies']; + $forum_topics_posts[$post_data['forum_id']]['forum_posts'] += $post_data['topic_replies']; + } + } + + $post_approve_sql[] = $post_id; + + // If the post is newer than the last post information stored we need to update the forum information + if ($post_data['post_time'] >= $post_data['forum_last_post_time']) + { + $update_forum_information = true; + } + } + + if (sizeof($topic_approve_sql)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_approved = 1 + WHERE ' . $db->sql_in_set('topic_id', $topic_approve_sql); + $db->sql_query($sql); + } + + if (sizeof($post_approve_sql)) + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_approved = 1 + WHERE ' . $db->sql_in_set('post_id', $post_approve_sql); + $db->sql_query($sql); + } + + foreach ($approve_log as $log_data) + { + add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_APPROVED' : 'LOG_POST_APPROVED', $log_data['post_subject']); + } + + if (sizeof($topic_replies_sql)) + { + foreach ($topic_replies_sql as $topic_id => $num_replies) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_replies = topic_replies + $num_replies + WHERE topic_id = $topic_id"; + $db->sql_query($sql); + } + } + + if (sizeof($forum_topics_posts)) + { + foreach ($forum_topics_posts as $forum_id => $row) + { + $sql = 'UPDATE ' . FORUMS_TABLE . ' + SET '; + $sql .= ($row['forum_topics']) ? "forum_topics = forum_topics + {$row['forum_topics']}" : ''; + $sql .= ($row['forum_topics'] && $row['forum_posts']) ? ', ' : ''; + $sql .= ($row['forum_posts']) ? "forum_posts = forum_posts + {$row['forum_posts']}" : ''; + $sql .= " WHERE forum_id = $forum_id"; + + $db->sql_query($sql); + } + } + + if (sizeof($user_posts_sql)) + { + // Try to minimize the query count by merging users with the same post count additions + $user_posts_update = array(); + + foreach ($user_posts_sql as $user_id => $user_posts) + { + $user_posts_update[$user_posts][] = $user_id; + } + + foreach ($user_posts_update as $user_posts => $user_id_ary) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_posts = user_posts + ' . $user_posts . ' + WHERE ' . $db->sql_in_set('user_id', $user_id_ary); + $db->sql_query($sql); + } + } + + if ($total_topics) + { + set_config('num_topics', $config['num_topics'] + $total_topics, true); + } + + if ($total_posts) + { + set_config('num_posts', $config['num_posts'] + $total_posts, true); + } + unset($topic_approve_sql, $topic_replies_sql, $post_approve_sql); + + update_post_information('topic', array_keys($topic_id_list)); + + if ($update_forum_information) + { + update_post_information('forum', array_keys($forum_id_list)); + } + unset($topic_id_list, $forum_id_list); + + $messenger = new messenger(); + + // Notify Poster? + if ($notify_poster) + { + foreach ($post_info as $post_id => $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + + $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_approved' : 'post_approved'; + + $messenger->template($email_template, $post_data['user_lang']); + + $messenger->to($post_data['user_email'], $post_data['username']); + $messenger->im($post_data['user_jabber'], $post_data['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($post_data['username']), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title'])), + + 'U_VIEW_TOPIC' => generate_board_url() . '/viewtopic.' . PHP_EXT . "?f={$post_data['forum_id']}&t={$post_data['topic_id']}&e=0", + 'U_VIEW_POST' => generate_board_url() . '/viewtopic.' . PHP_EXT . "?f={$post_data['forum_id']}&t={$post_data['topic_id']}&p=$post_id&e=$post_id") + ); + + $messenger->send($post_data['user_notify_type']); + } + } + + $messenger->save_queue(); + + // Send out normal user notifications + $email_sig = str_replace('<br />', "\n", "-- \n" . $config['board_email_sig']); + + foreach ($post_info as $post_id => $post_data) + { + if ($post_id == $post_data['topic_first_post_id'] && $post_id == $post_data['topic_last_post_id']) + { + // Forum Notifications + user_notification('post', $post_data['topic_title'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + } + else + { + // Topic Notifications + user_notification('reply', $post_data['post_subject'], $post_data['topic_title'], $post_data['forum_name'], $post_data['forum_id'], $post_data['topic_id'], $post_id); + } + } + + if (sizeof($post_id_list) == 1) + { + $post_data = $post_info[$post_id_list[0]]; + $post_url = append_sid('viewtopic', "f={$post_data['forum_id']}&t={$post_data['topic_id']}&p={$post_data['post_id']}") . '#p' . $post_data['post_id']; + } + unset($post_info); + + if ($total_topics) + { + $success_msg = ($total_topics == 1) ? 'TOPIC_APPROVED_SUCCESS' : 'TOPICS_APPROVED_SUCCESS'; + } + else + { + $success_msg = (sizeof($post_id_list) == 1) ? 'POST_APPROVED_SUCCESS' : 'POSTS_APPROVED_SUCCESS'; + } + } + else + { + $show_notify = false; + + foreach ($post_info as $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + else + { + $show_notify = true; + break; + } + } + + $template->assign_vars(array( + 'S_NOTIFY_POSTER' => $show_notify, + 'S_APPROVE' => true) + ); + + confirm_box(false, 'APPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + + // If approving one post, also give links back to post... + $add_message = ''; + if (sizeof($post_id_list) == 1 && !empty($post_url)) + { + $add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>'); + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message); + } +} + +/** +* Disapprove Post/Topic +*/ +function disapprove_post($post_id_list, $id, $mode) +{ + global $db, $template, $user, $config; + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) + { + trigger_error('NOT_AUTHORISED'); + } + + $redirect = request_var('redirect', build_url(array('t', 'mode', 'quickmod')) . "&mode=$mode"); + $reason = utf8_normalize_nfc(request_var('reason', '', true)); + $reason_id = request_var('reason_id', 0); + $success_msg = $additional_msg = ''; + + $s_hidden_fields = build_hidden_fields(array( + 'i' => $id, + 'mode' => $mode, + 'post_id_list' => $post_id_list, + 'action' => 'disapprove', + 'redirect' => $redirect) + ); + + $notify_poster = request::is_set('notify_poster'); + $disapprove_reason = ''; + + if ($reason_id) + { + $sql = 'SELECT reason_title, reason_description + FROM ' . REPORTS_REASONS_TABLE . " + WHERE reason_id = $reason_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row || (!$reason && strtolower($row['reason_title']) == 'other')) + { + $additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; + } + else + { + // If the reason is defined within the language file, we will use the localized version, else just use the database entry... + $disapprove_reason = (strtolower($row['reason_title']) != 'other') ? ((isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) ? $user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])] : $row['reason_description']) : ''; + $disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + + if (isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) + { + $disapprove_reason_lang = strtoupper($row['reason_title']); + } + + $email_disapprove_reason = $disapprove_reason; + } + } + + $post_info = get_post_data($post_id_list, 'm_approve'); + + if (!$additional_message && confirm_box(true)) + { + + // If Topic -> forum_topics_real -= 1 + // If Post -> topic_replies_real -= 1 + + $num_disapproved = 0; + $forum_topics_real = $topic_id_list = $forum_id_list = $topic_replies_real_sql = $post_disapprove_sql = $disapprove_log = array(); + + foreach ($post_info as $post_id => $post_data) + { + $topic_id_list[$post_data['topic_id']] = 1; + + if ($post_data['forum_id']) + { + $forum_id_list[$post_data['forum_id']] = 1; + } + + // Topic or Post. ;) + /** + * @todo this probably is a different method than the one used by delete_posts, does this cause counter inconsistency? + */ + if ($post_data['topic_first_post_id'] == $post_id && $post_data['topic_last_post_id'] == $post_id) + { + if ($post_data['forum_id']) + { + if (!isset($forum_topics_real[$post_data['forum_id']])) + { + $forum_topics_real[$post_data['forum_id']] = 0; + } + $forum_topics_real[$post_data['forum_id']]++; + $num_disapproved++; + } + + $disapprove_log[] = array( + 'type' => 'topic', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => 0, // useless to log a topic id, as it will be deleted + ); + } + else + { + if (!isset($topic_replies_real_sql[$post_data['topic_id']])) + { + $topic_replies_real_sql[$post_data['topic_id']] = 0; + } + $topic_replies_real_sql[$post_data['topic_id']]++; + + $disapprove_log[] = array( + 'type' => 'post', + 'post_subject' => $post_data['post_subject'], + 'forum_id' => $post_data['forum_id'], + 'topic_id' => $post_data['topic_id'], + ); + } + + $post_disapprove_sql[] = $post_id; + } + + unset($post_data); + + if (sizeof($forum_topics_real)) + { + foreach ($forum_topics_real as $forum_id => $topics_real) + { + $sql = 'UPDATE ' . FORUMS_TABLE . " + SET forum_topics_real = forum_topics_real - $topics_real + WHERE forum_id = $forum_id"; + $db->sql_query($sql); + } + } + + if (sizeof($topic_replies_real_sql)) + { + foreach ($topic_replies_real_sql as $topic_id => $num_replies) + { + $sql = 'UPDATE ' . TOPICS_TABLE . " + SET topic_replies_real = topic_replies_real - $num_replies + WHERE topic_id = $topic_id"; + $db->sql_query($sql); + } + } + + if (sizeof($post_disapprove_sql)) + { + if (!function_exists('delete_posts')) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); + } + + // We do not check for permissions here, because the moderator allowed approval/disapproval should be allowed to delete the disapproved posts + delete_posts('post_id', $post_disapprove_sql); + + foreach ($disapprove_log as $log_data) + { + add_log('mod', $log_data['forum_id'], $log_data['topic_id'], ($log_data['type'] == 'topic') ? 'LOG_TOPIC_DISAPPROVED' : 'LOG_POST_DISAPPROVED', $log_data['post_subject'], $disapprove_reason); + } + } + unset($post_disapprove_sql, $topic_replies_real_sql); + + update_post_information('topic', array_keys($topic_id_list)); + + if (sizeof($forum_id_list)) + { + update_post_information('forum', array_keys($forum_id_list)); + } + unset($topic_id_list, $forum_id_list); + + $messenger = new messenger(); + + // Notify Poster? + if ($notify_poster) + { + $lang_reasons = array(); + + foreach ($post_info as $post_id => $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + + if (isset($disapprove_reason_lang)) + { + // Okay we need to get the reason from the posters language + if (!isset($lang_reasons[$post_data['user_lang']])) + { + // Assign the current users translation as the default, this is not ideal but getting the board default adds another layer of complexity. + $lang_reasons[$post_data['user_lang']] = $user->lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + + // Only load up the language pack if the language is different to the current one + if ($post_data['user_lang'] != $user->lang_name && file_exists(PHPBB_ROOT_PATH . '/language/' . $post_data['user_lang'] . '/mcp.' . PHP_EXT)) + { + // Load up the language pack + $lang = array(); + @include(PHPBB_ROOT_PATH . '/language/' . $post_data['user_lang'] . '/mcp.' . PHP_EXT); + + // If we find the reason in this language pack use it + if (isset($lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang])) + { + $lang_reasons[$post_data['user_lang']] = $lang['report_reasons']['DESCRIPTION'][$disapprove_reason_lang]; + } + + unset($lang); // Free memory + } + } + + $email_disapprove_reason = $lang_reasons[$post_data['user_lang']]; + $email_disapprove_reason .= ($reason) ? "\n\n" . $reason : ''; + } + + $email_template = ($post_data['post_id'] == $post_data['topic_first_post_id'] && $post_data['post_id'] == $post_data['topic_last_post_id']) ? 'topic_disapproved' : 'post_disapproved'; + + $messenger->template($email_template, $post_data['user_lang']); + + $messenger->to($post_data['user_email'], $post_data['username']); + $messenger->im($post_data['user_jabber'], $post_data['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($post_data['username']), + 'REASON' => htmlspecialchars_decode($email_disapprove_reason), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_data['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_data['topic_title']))) + ); + + $messenger->send($post_data['user_notify_type']); + } + + unset($lang_reasons); + } + unset($post_info, $disapprove_reason, $email_disapprove_reason, $disapprove_reason_lang); + + $messenger->save_queue(); + + if (sizeof($forum_topics_real)) + { + $success_msg = ($num_disapproved == 1) ? 'TOPIC_DISAPPROVED_SUCCESS' : 'TOPICS_DISAPPROVED_SUCCESS'; + } + else + { + $success_msg = (sizeof($post_id_list) == 1) ? 'POST_DISAPPROVED_SUCCESS' : 'POSTS_DISAPPROVED_SUCCESS'; + } + } + else + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + display_reasons($reason_id); + + $show_notify = false; + + foreach ($post_info as $post_data) + { + if ($post_data['poster_id'] == ANONYMOUS) + { + continue; + } + else + { + $show_notify = true; + break; + } + } + + $template->assign_vars(array( + 'S_NOTIFY_POSTER' => $show_notify, + 'S_APPROVE' => false, + 'REASON' => $reason, + 'ADDITIONAL_MSG' => $additional_msg) + ); + + confirm_box(false, 'DISAPPROVE_POST' . ((sizeof($post_id_list) == 1) ? '' : 'S'), $s_hidden_fields, 'mcp_approve.html'); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>')); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_reports.php b/phpBB/modules/mcp/mcp_reports.php new file mode 100644 index 0000000000..7e6bae1dc1 --- /dev/null +++ b/phpBB/modules/mcp/mcp_reports.php @@ -0,0 +1,656 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_reports +* Handling the reports queue +* @package mcp +*/ +class mcp_reports +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $cache; + global $config, $action; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + + $forum_id = request_var('f', 0); + $start = request_var('start', 0); + + $this->page_title = 'MCP_REPORTS'; + + switch ($action) + { + case 'close': + case 'delete': + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $report_id_list = request_var('report_id_list', array(0)); + + if (!sizeof($report_id_list)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + close_report($report_id_list, $mode, $action); + + break; + } + + switch ($mode) + { + case 'report_details': + + $user->add_lang(array('posting', 'viewforum', 'viewtopic')); + + $post_id = request_var('p', 0); + + // closed reports are accessed by report id + $report_id = request_var('r', 0); + + $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour + FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u + WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . ' + AND rr.reason_id = r.reason_id + AND r.user_id = u.user_id + ORDER BY report_closed ASC'; + $result = $db->sql_query_limit($sql, 1); + $report = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$report) + { + trigger_error('NO_REPORT'); + } + + if (!$report_id && $report['report_closed']) + { + trigger_error('REPORT_CLOSED'); + } + + $post_id = $report['post_id']; + $report_id = $report['report_id']; + + $post_info = get_post_data(array($post_id), 'm_report', true); + + if (!sizeof($post_info)) + { + trigger_error('NO_REPORT_SELECTED'); + } + + $post_info = $post_info[$post_id]; + + $reason = array('title' => $report['reason_title'], 'description' => $report['reason_description']); + if (isset($user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]) && isset($user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])])) + { + $reason['description'] = $user->lang['report_reasons']['DESCRIPTION'][strtoupper($reason['title'])]; + $reason['title'] = $user->lang['report_reasons']['TITLE'][strtoupper($reason['title'])]; + } + + if (topic_review($post_info['topic_id'], $post_info['forum_id'], 'topic_review', 0, false)) + { + $template->assign_vars(array( + 'S_TOPIC_REVIEW' => true, + 'TOPIC_TITLE' => $post_info['topic_title']) + ); + } + + $topic_tracking_info = $extensions = $attachments = array(); + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($post_info['topic_id'] => $post_info); + $topic_tracking_info = get_topic_tracking($post_info['forum_id'], $post_info['topic_id'], $tmp_topic_data, array($post_info['forum_id'] => $post_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($post_info['forum_id'], $post_info['topic_id']); + } + + $post_unread = (isset($topic_tracking_info[$post_info['topic_id']]) && $post_info['post_time'] > $topic_tracking_info[$post_info['topic_id']]) ? true : false; + + // Process message, leave it uncensored + $message = $post_info['post_text']; + + if ($post_info['bbcode_bitfield']) + { + include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode($post_info['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $post_info['bbcode_uid'], $post_info['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if ($post_info['post_attachment'] && $auth->acl_get('u_download') && $auth->acl_get('f_download', $post_info['forum_id'])) + { + $extensions = cache::obtain_attach_extensions($post_info['forum_id']); + + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE post_msg_id = ' . $post_id . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($attachments)) + { + $update_count = array(); + parse_attachments($post_info['forum_id'], $message, $attachments, $update_count); + } + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + } + + $template->assign_vars(array( + 'S_MCP_REPORT' => true, + 'S_CLOSE_ACTION' => append_sid('mcp', 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'S_CAN_VIEWIP' => $auth->acl_get('m_info', $post_info['forum_id']), + 'S_POST_REPORTED' => $post_info['post_reported'], + 'S_POST_UNAPPROVED' => !$post_info['post_approved'], + 'S_POST_LOCKED' => $post_info['post_edit_locked'], + 'S_USER_NOTES' => true, + + 'U_EDIT' => ($auth->acl_get('m_edit', $post_info['forum_id'])) ? append_sid('posting', "mode=edit&f={$post_info['forum_id']}&p={$post_info['post_id']}") : '', + 'U_MCP_APPROVE' => append_sid('mcp', 'i=queue&mode=approve_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORT' => append_sid('mcp', 'i=reports&mode=report_details&f=' . $post_info['forum_id'] . '&p=' . $post_id), + 'U_MCP_REPORTER_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $report['user_id']), + 'U_MCP_USER_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $post_info['user_id']), + 'U_MCP_WARN_REPORTER' => ($auth->acl_get('m_warn')) ? append_sid('mcp', 'i=warn&mode=warn_user&u=' . $report['user_id']) : '', + 'U_MCP_WARN_USER' => ($auth->acl_get('m_warn')) ? append_sid('mcp', 'i=warn&mode=warn_user&u=' . $post_info['user_id']) : '', + 'U_VIEW_FORUM' => append_sid('viewforum', 'f=' . $post_info['forum_id']), + 'U_VIEW_POST' => append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&p=' . $post_info['post_id'] . '#p' . $post_info['post_id']), + 'U_VIEW_TOPIC' => append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']), + + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['EDIT_POST']), + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', $user->lang['POST_UNAPPROVED']), + + 'RETURN_REPORTS' => sprintf($user->lang['RETURN_REPORTS'], '<a href="' . append_sid('mcp', 'i=reports' . (($post_info['post_reported']) ? '&mode=reports' : '&mode=reports_closed') . '&start=' . $start . '&f=' . $post_info['forum_id']) . '">', '</a>'), + 'REPORTED_IMG' => $user->img('icon_topic_reported', $user->lang['POST_REPORTED']), + 'REPORT_DATE' => $user->format_date($report['report_time']), + 'REPORT_ID' => $report_id, + 'REPORT_REASON_TITLE' => $reason['title'], + 'REPORT_REASON_DESCRIPTION' => $reason['description'], + 'REPORT_TEXT' => $report['report_text'], + + 'POST_AUTHOR_FULL' => get_username_string('full', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'POST_AUTHOR' => get_username_string('username', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $post_info['user_id'], $post_info['username'], $post_info['user_colour'], $post_info['post_username']), + + 'REPORTER_FULL' => get_username_string('full', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $report['user_id'], $report['username'], $report['user_colour']), + 'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']), + 'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']), + + 'POST_PREVIEW' => $message, + 'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_DATE' => $user->format_date($post_info['post_time']), + 'POST_IP' => $post_info['poster_ip'], + 'POST_IPADDR' => ($auth->acl_get('m_info', $post_info['forum_id']) && request_var('lookup', '')) ? @gethostbyaddr($post_info['poster_ip']) : '', + 'POST_ID' => $post_info['post_id'], + + 'U_LOOKUP_IP' => ($auth->acl_get('m_info', $post_info['forum_id'])) ? $this->u_action . '&r=' . $report_id . '&p=' . $post_id . '&f=' . $forum_id . '&lookup=' . $post_info['poster_ip'] . '#ip' : '', + )); + + $this->tpl_name = 'mcp_post'; + + break; + + case 'reports': + case 'reports_closed': + $topic_id = request_var('t', 0); + + $forum_info = array(); + $forum_list_reports = get_forum_list('m_report', false, true); + $forum_list_read = array_flip(get_forum_list('f_read', true, true)); // Flipped so we can isset() the forum IDs + + // Remove forums we cannot read + foreach ($forum_list_reports as $k => $forum_data) + { + if (!isset($forum_list_read[$forum_data['forum_id']])) + { + unset($forum_list_reports[$k]); + } + } + unset($forum_list_read); + + if ($topic_id && $forum_id) + { + $topic_info = get_topic_data(array($topic_id)); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + $topic_info = $topic_info[$topic_id]; + $forum_id = $topic_info['forum_id']; + } + else if ($topic_id && !$forum_id) + { + $topic_id = 0; + } + + $forum_list = array(); + + if (!$forum_id) + { + foreach ($forum_list_reports as $row) + { + $forum_list[] = $row['forum_id']; + } + + if (!sizeof($forum_list)) + { + trigger_error('NOT_MODERATOR'); + } + + $global_id = $forum_list[0]; + + $sql = 'SELECT SUM(forum_topics) as sum_forum_topics + FROM ' . FORUMS_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forum_list); + $result = $db->sql_query($sql); + $forum_info['forum_topics'] = (int) $db->sql_fetchfield('sum_forum_topics'); + $db->sql_freeresult($result); + } + else + { + $forum_info = get_forum_data(array($forum_id), 'm_report'); + + if (!sizeof($forum_info)) + { + trigger_error('NOT_MODERATOR'); + } + + $forum_info = $forum_info[$forum_id]; + $forum_list = array($forum_id); + $global_id = $forum_id; + } + + $forum_list[] = 0; + $forum_data = array(); + + $forum_options = '<option value="0"' . (($forum_id == 0) ? ' selected="selected"' : '') . '>' . $user->lang['ALL_FORUMS'] . '</option>'; + foreach ($forum_list_reports as $row) + { + $forum_options .= '<option value="' . $row['forum_id'] . '"' . (($forum_id == $row['forum_id']) ? ' selected="selected"' : '') . '>' . str_repeat(' ', $row['padding']) . $row['forum_name'] . '</option>'; + $forum_data[$row['forum_id']] = $row; + } + unset($forum_list_reports); + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting($mode, $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $forum_topics = ($total == -1) ? $forum_info['forum_topics'] : $total; + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($mode == 'reports') + { + $report_state = 'AND p.post_reported = 1 AND r.report_closed = 0'; + } + else + { + $report_state = 'AND r.report_closed = 1'; + } + + $sql = 'SELECT r.report_id + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . REPORTS_TABLE . ' r ' . (($sort_order_sql[0] == 'u') ? ', ' . USERS_TABLE . ' u' : '') . (($sort_order_sql[0] == 'r') ? ', ' . USERS_TABLE . ' ru' : '') . ' + WHERE ' . $db->sql_in_set('p.forum_id', $forum_list) . " + $report_state + AND r.post_id = p.post_id + " . (($sort_order_sql[0] == 'u') ? 'AND u.user_id = p.poster_id' : '') . ' + ' . (($sort_order_sql[0] == 'r') ? 'AND ru.user_id = p.poster_id' : '') . ' + ' . (($topic_id) ? 'AND p.topic_id = ' . $topic_id : '') . " + AND t.topic_id = p.topic_id + $limit_time_sql + ORDER BY $sort_order_sql"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $i = 0; + $report_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $report_ids[] = $row['report_id']; + $row_num[$row['report_id']] = $i++; + } + $db->sql_freeresult($result); + + if (sizeof($report_ids)) + { + $sql = 'SELECT t.forum_id, t.topic_id, t.topic_title, p.post_id, p.post_subject, p.post_username, p.poster_id, p.post_time, u.username, u.username_clean, u.user_colour, r.user_id as reporter_id, ru.username as reporter_name, ru.user_colour as reporter_colour, r.report_time, r.report_id + FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . ' u, ' . USERS_TABLE . ' ru + WHERE ' . $db->sql_in_set('r.report_id', $report_ids) . ' + AND t.topic_id = p.topic_id + AND r.post_id = p.post_id + AND u.user_id = p.poster_id + AND ru.user_id = r.user_id + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query($sql); + + $report_data = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $global_topic = ($row['forum_id']) ? false : true; + if ($global_topic) + { + $row['forum_id'] = $global_id; + } + + $template->assign_block_vars('postrow', array( + 'U_VIEWFORUM' => (!$global_topic) ? append_sid('viewforum', 'f=' . $row['forum_id']) : '', + 'U_VIEWPOST' => append_sid('viewtopic', 'f=' . $row['forum_id'] . '&p=' . $row['post_id']) . '#p' . $row['post_id'], + 'U_VIEW_DETAILS' => append_sid('mcp', "i=reports&start=$start&mode=report_details&f={$row['forum_id']}&r={$row['report_id']}"), + + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'REPORTER_FULL' => get_username_string('full', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER_COLOUR' => get_username_string('colour', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'REPORTER' => get_username_string('username', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + 'U_REPORTER' => get_username_string('profile', $row['reporter_id'], $row['reporter_name'], $row['reporter_colour']), + + 'FORUM_NAME' => (!$global_topic) ? $forum_data[$row['forum_id']]['forum_name'] : $user->lang['GLOBAL_ANNOUNCEMENT'], + 'POST_ID' => $row['post_id'], + 'POST_SUBJECT' => ($row['post_subject']) ? $row['post_subject'] : $user->lang['NO_SUBJECT'], + 'POST_TIME' => $user->format_date($row['post_time']), + 'REPORT_ID' => $row['report_id'], + 'REPORT_TIME' => $user->format_date($row['report_time']), + 'TOPIC_TITLE' => $row['topic_title']) + ); + } + $db->sql_freeresult($result); + unset($report_ids, $row); + } + + // Now display the page + $template->assign_vars(array( + 'L_EXPLAIN' => ($mode == 'reports') ? $user->lang['MCP_REPORTS_OPEN_EXPLAIN'] : $user->lang['MCP_REPORTS_CLOSED_EXPLAIN'], + 'L_TITLE' => ($mode == 'reports') ? $user->lang['MCP_REPORTS_OPEN'] : $user->lang['MCP_REPORTS_CLOSED'], + 'L_ONLY_TOPIC' => ($topic_id) ? sprintf($user->lang['ONLY_TOPIC'], $topic_info['topic_title']) : '', + + 'S_MCP_ACTION' => $this->u_action, + 'S_FORUM_OPTIONS' => $forum_options, + 'S_CLOSED' => ($mode == 'reports_closed') ? true : false, + + 'PAGINATION' => generate_pagination($this->u_action . "&f=$forum_id&t=$topic_id&st=$sort_days&sk=$sort_key&sd=$sort_dir", $total, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($total, $config['topics_per_page'], $start), + 'TOPIC_ID' => $topic_id, + 'TOTAL' => $total, + 'TOTAL_REPORTS' => ($total == 1) ? $user->lang['LIST_REPORT'] : sprintf($user->lang['LIST_REPORTS'], $total), + ) + ); + + $this->tpl_name = 'mcp_reports'; + break; + } + } +} + +/** +* Closes a report +*/ +function close_report($report_id_list, $mode, $action) +{ + global $db, $template, $user, $config; + + $sql = 'SELECT r.post_id + FROM ' . REPORTS_TABLE . ' r + WHERE ' . $db->sql_in_set('r.report_id', $report_id_list); + $result = $db->sql_query($sql); + + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + $post_id_list[] = $row['post_id']; + } + $post_id_list = array_unique($post_id_list); + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_report'))) + { + trigger_error('NOT_AUTHORISED'); + } + + if ($action == 'delete' && strpos($user->data['session_page'], 'mode=report_details') !== false) + { + $redirect = request_var('redirect', build_url(array('mode', 'r', 'quickmod')) . '&mode=reports'); + } + else if ($action == 'close' && !request_var('r', 0)) + { + $redirect = request_var('redirect', build_url(array('mode', 'p', 'quickmod')) . '&mode=reports'); + } + else + { + $redirect = request_var('redirect', build_url(array('quickmod'))); + } + $success_msg = ''; + $forum_ids = array(); + $topic_ids = array(); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'reports', + 'mode' => $mode, + 'report_id_list' => $report_id_list, + 'action' => $action, + 'redirect' => $redirect) + ); + + if (confirm_box(true)) + { + $post_info = get_post_data($post_id_list, 'm_report'); + + $sql = 'SELECT r.report_id, r.post_id, r.report_closed, r.user_id, r.user_notify, u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type + FROM ' . REPORTS_TABLE . ' r, ' . USERS_TABLE . ' u + WHERE ' . $db->sql_in_set('r.report_id', $report_id_list) . ' + ' . (($action == 'close') ? 'AND r.report_closed = 0' : '') . ' + AND r.user_id = u.user_id'; + $result = $db->sql_query($sql); + + $reports = $close_report_posts = $close_report_topics = $notify_reporters = $report_id_list = array(); + while ($report = $db->sql_fetchrow($result)) + { + $reports[$report['report_id']] = $report; + $report_id_list[] = $report['report_id']; + + if (!$report['report_closed']) + { + $close_report_posts[] = $report['post_id']; + $close_report_topics[] = $post_info[$report['post_id']]['topic_id']; + } + + if ($report['user_notify'] && !$report['report_closed']) + { + $notify_reporters[$report['report_id']] = &$reports[$report['report_id']]; + } + } + $db->sql_freeresult($result); + + if (sizeof($reports)) + { + $close_report_posts = array_unique($close_report_posts); + $close_report_topics = array_unique($close_report_topics); + + if (sizeof($close_report_posts)) + { + // Get a list of topics that still contain reported posts + $sql = 'SELECT DISTINCT topic_id + FROM ' . POSTS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' + AND post_reported = 1 + AND ' . $db->sql_in_set('post_id', $close_report_posts, true); + $result = $db->sql_query($sql); + + $keep_report_topics = array(); + while ($row = $db->sql_fetchrow($result)) + { + $keep_report_topics[] = $row['topic_id']; + } + $db->sql_freeresult($result); + + $close_report_topics = array_diff($close_report_topics, $keep_report_topics); + unset($keep_report_topics); + } + + $db->sql_transaction('begin'); + + if ($action == 'close') + { + $sql = 'UPDATE ' . REPORTS_TABLE . ' + SET report_closed = 1 + WHERE ' . $db->sql_in_set('report_id', $report_id_list); + } + else + { + $sql = 'DELETE FROM ' . REPORTS_TABLE . ' + WHERE ' . $db->sql_in_set('report_id', $report_id_list); + } + $db->sql_query($sql); + + + if (sizeof($close_report_posts)) + { + $sql = 'UPDATE ' . POSTS_TABLE . ' + SET post_reported = 0 + WHERE ' . $db->sql_in_set('post_id', $close_report_posts); + $db->sql_query($sql); + + if (sizeof($close_report_topics)) + { + $sql = 'UPDATE ' . TOPICS_TABLE . ' + SET topic_reported = 0 + WHERE ' . $db->sql_in_set('topic_id', $close_report_topics) . ' + OR ' . $db->sql_in_set('topic_moved_id', $close_report_topics); + $db->sql_query($sql); + } + } + + $db->sql_transaction('commit'); + } + unset($close_report_posts, $close_report_topics); + + foreach ($reports as $report) + { + add_log('mod', $post_info[$report['post_id']]['forum_id'], $post_info[$report['post_id']]['topic_id'], 'LOG_REPORT_' . strtoupper($action) . 'D', $post_info[$report['post_id']]['post_subject']); + } + + $messenger = new messenger(); + + // Notify reporters + if (sizeof($notify_reporters)) + { + foreach ($notify_reporters as $report_id => $reporter) + { + if ($reporter['user_id'] == ANONYMOUS) + { + continue; + } + + $post_id = $reporter['post_id']; + + $messenger->template('report_' . $action . 'd', $reporter['user_lang']); + + $messenger->to($reporter['user_email'], $reporter['username']); + $messenger->im($reporter['user_jabber'], $reporter['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($reporter['username']), + 'CLOSER_NAME' => htmlspecialchars_decode($user->data['username']), + 'POST_SUBJECT' => htmlspecialchars_decode(censor_text($post_info[$post_id]['post_subject'])), + 'TOPIC_TITLE' => htmlspecialchars_decode(censor_text($post_info[$post_id]['topic_title']))) + ); + + $messenger->send($reporter['user_notify_type']); + } + } + + foreach ($post_info as $post) + { + $forum_ids[$post['forum_id']] = $post['forum_id']; + $topic_ids[$post['topic_id']] = $post['topic_id']; + } + + unset($notify_reporters, $post_info, $reports); + + $messenger->save_queue(); + + $success_msg = (sizeof($report_id_list) == 1) ? 'REPORT_' . strtoupper($action) . 'D_SUCCESS' : 'REPORTS_' . strtoupper($action) . 'D_SUCCESS'; + } + else + { + confirm_box(false, $user->lang[strtoupper($action) . '_REPORT' . ((sizeof($report_id_list) == 1) ? '' : 'S') . '_CONFIRM'], $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + redirect($redirect); + } + else + { + meta_refresh(3, $redirect); + $return_forum = ''; + if (sizeof($forum_ids == 1)) + { + $return_forum = sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid('viewforum', 'f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; + } + $return_topic = ''; + if (sizeof($topic_ids == 1)) + { + $return_topic = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', 't=' . current($topic_ids) . '&f=' . current($forum_ids)) . '">', '</a>') . '<br /><br />'; + } + + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_forum . $return_topic . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>')); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_topic.php b/phpBB/modules/mcp/mcp_topic.php new file mode 100644 index 0000000000..bd1bc4f659 --- /dev/null +++ b/phpBB/modules/mcp/mcp_topic.php @@ -0,0 +1,633 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View topic in MCP +*/ +function mcp_topic_view($id, $mode, $action) +{ + global $template, $db, $user, $auth, $cache, $config; + + $url = append_sid(PHPBB_ROOT_PATH. 'mcp.' . PHP_EXT . '?' . extra_url()); + + $user->add_lang('viewtopic'); + + $topic_id = request_var('t', 0); + $topic_info = get_topic_data(array($topic_id), false, true); + + if (!sizeof($topic_info)) + { + trigger_error('TOPIC_NOT_EXIST'); + } + + $topic_info = $topic_info[$topic_id]; + + // Set up some vars + $icon_id = request_var('icon', 0); + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $start = request_var('start', 0); + $sort_days_old = request_var('st_old', 0); + $forum_id = request_var('f', 0); + $to_topic_id = request_var('to_topic_id', 0); + $to_forum_id = request_var('to_forum_id', 0); + $sort = request::is_set_post('sort'); + $submitted_id_list = request_var('post_ids', array(0)); + $checked_ids = $post_id_list = request_var('post_id_list', array(0)); + + // Split Topic? + if ($action == 'split_all' || $action == 'split_beyond') + { + if (!$sort) + { + split_topic($action, $topic_id, $to_forum_id, $subject); + } + $action = 'split'; + } + + // Merge Posts? + if ($action == 'merge_posts') + { + if (!$sort) + { + merge_posts($topic_id, $to_topic_id); + } + $action = 'merge'; + } + + if ($action == 'split' && !$subject) + { + $subject = $topic_info['topic_title']; + } + + // Approve posts? + if ($action == 'approve' && $auth->acl_get('m_approve', $topic_info['forum_id'])) + { + include(PHPBB_ROOT_PATH . 'includes/mcp/mcp_queue.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + if (!$sort) + { + approve_post($post_id_list, $id, $mode); + } + } + + // Jumpbox, sort selects and that kind of things + make_jumpbox($url . "&i=$id&mode=forum_view", $topic_info['forum_id'], false, 'm_', true); + $where_sql = ($action == 'reports') ? 'WHERE post_reported = 1 AND ' : 'WHERE'; + + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $topic_info['forum_id'], $topic_id, $where_sql); + + $limit_time_sql = ($sort_days) ? 'AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($total == -1) + { + $total = $topic_info['topic_replies'] + 1; + } + + $posts_per_page = max(0, request_var('posts_per_page', intval($config['posts_per_page']))); + if ($posts_per_page == 0) + { + $posts_per_page = $total; + } + + if ((!empty($sort_days_old) && $sort_days_old != $sort_days) || $total <= $posts_per_page) + { + $start = 0; + } + + // Make sure $start is set to the last page if it exceeds the amount + if ($start < 0 || $start >= $total) + { + $start = ($start < 0) ? 0 : floor(($total - 1) / $posts_per_page) * $posts_per_page; + } + + $sql = 'SELECT u.username, u.username_clean, u.user_colour, p.* + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE ' . (($action == 'reports') ? 'p.post_reported = 1 AND ' : '') . ' + p.topic_id = ' . $topic_id . ' ' . + ((!$auth->acl_get('m_approve', $topic_info['forum_id'])) ? ' AND p.post_approved = 1 ' : '') . ' + AND p.poster_id = u.user_id ' . + $limit_time_sql . ' + ORDER BY ' . $sort_order_sql; + $result = $db->sql_query_limit($sql, $posts_per_page, $start); + + $rowset = $post_id_list = array(); + $bbcode_bitfield = ''; + while ($row = $db->sql_fetchrow($result)) + { + $rowset[] = $row; + $post_id_list[] = $row['post_id']; + $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); + } + $db->sql_freeresult($result); + + if ($bbcode_bitfield !== '') + { + include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode(base64_encode($bbcode_bitfield)); + } + + $topic_tracking_info = array(); + + // Get topic tracking info + if ($config['load_db_lastread']) + { + $tmp_topic_data = array($topic_id => $topic_info); + $topic_tracking_info = get_topic_tracking($topic_info['forum_id'], $topic_id, $tmp_topic_data, array($topic_info['forum_id'] => $topic_info['forum_mark_time'])); + unset($tmp_topic_data); + } + else + { + $topic_tracking_info = get_complete_topic_tracking($topic_info['forum_id'], $topic_id); + } + + $has_unapproved_posts = false; + + // Grab extensions + $extensions = $attachments = array(); + if ($topic_info['topic_attachment'] && sizeof($post_id_list)) + { + $extensions = cache::obtain_attach_extensions($topic_info['forum_id']); + + // Get attachments... + if ($auth->acl_get('u_download') && $auth->acl_get('f_download', $topic_info['forum_id'])) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . ' + WHERE ' . $db->sql_in_set('post_msg_id', $post_id_list) . ' + AND in_message = 0 + ORDER BY filetime DESC, post_msg_id ASC'; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[$row['post_msg_id']][] = $row; + } + $db->sql_freeresult($result); + } + } + + foreach ($rowset as $i => $row) + { + $message = $row['post_text']; + $post_subject = ($row['post_subject'] != '') ? $row['post_subject'] : $topic_info['topic_title']; + + if ($row['bbcode_bitfield']) + { + $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + if (!empty($attachments[$row['post_id']])) + { + $update_count = array(); + parse_attachments($topic_info['forum_id'], $message, $attachments[$row['post_id']], $update_count); + } + + if (!$row['post_approved']) + { + $has_unapproved_posts = true; + } + + $post_unread = (isset($topic_tracking_info[$topic_id]) && $row['post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + $template->assign_block_vars('postrow', array( + 'POST_AUTHOR_FULL' => get_username_string('full', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR_COLOUR' => get_username_string('colour', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'POST_AUTHOR' => get_username_string('username', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + 'U_POST_AUTHOR' => get_username_string('profile', $row['poster_id'], $row['username'], $row['user_colour'], $row['post_username']), + + 'POST_DATE' => $user->format_date($row['post_time']), + 'POST_SUBJECT' => $post_subject, + 'MESSAGE' => $message, + 'POST_ID' => $row['post_id'], + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', 't=' . $topic_id) . '">', '</a>'), + + 'MINI_POST_IMG' => ($post_unread) ? $user->img('icon_post_target_unread', 'NEW_POST') : $user->img('icon_post_target', 'POST'), + + 'S_POST_REPORTED' => ($row['post_reported']) ? true : false, + 'S_POST_UNAPPROVED' => ($row['post_approved']) ? false : true, + 'S_CHECKED' => (($submitted_id_list && !in_array(intval($row['post_id']), $submitted_id_list)) || in_array(intval($row['post_id']), $checked_ids)) ? true : false, + 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, + + 'U_POST_DETAILS' => "$url&i=$id&p={$row['post_id']}&mode=post_details" . (($forum_id) ? "&f=$forum_id" : ''), + 'U_MCP_APPROVE' => ($auth->acl_get('m_approve', $topic_info['forum_id'])) ? append_sid('mcp', 'i=queue&mode=approve_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '', + 'U_MCP_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? append_sid('mcp', 'i=reports&mode=report_details&f=' . $topic_info['forum_id'] . '&p=' . $row['post_id']) : '') + ); + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (!empty($attachments[$row['post_id']])) + { + foreach ($attachments[$row['post_id']] as $attachment) + { + $template->assign_block_vars('postrow.attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + + unset($rowset[$i]); + } + + // Display topic icons for split topic + $s_topic_icons = false; + + if ($auth->acl_get('m_split', $topic_info['forum_id'])) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + $s_topic_icons = posting_gen_topic_icons('', $icon_id); + + // Has the user selected a topic for merge? + if ($to_topic_id) + { + $to_topic_info = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($to_topic_info)) + { + $to_topic_id = 0; + } + else + { + $to_topic_info = $to_topic_info[$to_topic_id]; + + if (!$to_topic_info['enable_icons'] || $auth->acl_get('!f_icons', $topic_info['forum_id'])) + { + $s_topic_icons = false; + } + } + } + } + + $s_hidden_fields = build_hidden_fields(array( + 'st_old' => $sort_days, + 'post_ids' => $post_id_list, + )); + + $template->assign_vars(array( + 'TOPIC_TITLE' => $topic_info['topic_title'], + 'U_VIEW_TOPIC' => append_sid('viewtopic', 'f=' . $topic_info['forum_id'] . '&t=' . $topic_info['topic_id']), + + 'TO_TOPIC_ID' => $to_topic_id, + 'TO_TOPIC_INFO' => ($to_topic_id) ? sprintf($user->lang['YOU_SELECTED_TOPIC'], $to_topic_id, '<a href="' . append_sid('viewtopic', 'f=' . $to_topic_info['forum_id'] . '&t=' . $to_topic_id) . '">' . $to_topic_info['topic_title'] . '</a>') : '', + + 'SPLIT_SUBJECT' => $subject, + 'POSTS_PER_PAGE' => $posts_per_page, + 'ACTION' => $action, + + 'REPORTED_IMG' => $user->img('icon_topic_reported', 'POST_REPORTED'), + 'UNAPPROVED_IMG' => $user->img('icon_topic_unapproved', 'POST_UNAPPROVED'), + + 'S_MCP_ACTION' => "$url&i=$id&mode=$mode&action=$action&start=$start", + 'S_FORUM_SELECT' => ($to_forum_id) ? make_forum_select($to_forum_id, false, false, true, true, true) : make_forum_select($topic_info['forum_id'], false, false, true, true, true), + 'S_CAN_SPLIT' => ($auth->acl_get('m_split', $topic_info['forum_id'])) ? true : false, + 'S_CAN_MERGE' => ($auth->acl_get('m_merge', $topic_info['forum_id'])) ? true : false, + 'S_CAN_DELETE' => ($auth->acl_get('m_delete', $topic_info['forum_id'])) ? true : false, + 'S_CAN_APPROVE' => ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false, + 'S_CAN_LOCK' => ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false, + 'S_CAN_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? true : false, + 'S_REPORT_VIEW' => ($action == 'reports') ? true : false, + 'S_MERGE_VIEW' => ($action == 'merge') ? true : false, + 'S_SPLIT_VIEW' => ($action == 'split') ? true : false, + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + + 'S_SHOW_TOPIC_ICONS' => $s_topic_icons, + 'S_TOPIC_ICON' => $icon_id, + + 'U_SELECT_TOPIC' => "$url&i=$id&mode=forum_view&action=merge_select" . (($forum_id) ? "&f=$forum_id" : ''), + + 'RETURN_TOPIC' => sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', "f={$topic_info['forum_id']}&t={$topic_info['topic_id']}&start=$start") . '">', '</a>'), + 'RETURN_FORUM' => sprintf($user->lang['RETURN_FORUM'], '<a href="' . append_sid('viewforum', "f={$topic_info['forum_id']}&start=$start") . '">', '</a>'), + + 'PAGE_NUMBER' => on_page($total, $posts_per_page, $start), + 'PAGINATION' => (!$posts_per_page) ? '' : generate_pagination(append_sid('mcp', "i=$id&t={$topic_info['topic_id']}&mode=$mode&action=$action&to_topic_id=$to_topic_id&posts_per_page=$posts_per_page&st=$sort_days&sk=$sort_key&sd=$sort_dir"), $total, $posts_per_page, $start), + 'TOTAL_POSTS' => ($total == 1) ? $user->lang['VIEW_TOPIC_POST'] : sprintf($user->lang['VIEW_TOPIC_POSTS'], $total), + )); +} + +/** +* Split topic +*/ +function split_topic($action, $topic_id, $to_forum_id, $subject) +{ + global $db, $template, $user, $auth, $config; + + $post_id_list = request_var('post_id_list', array(0)); + $forum_id = request_var('forum_id', 0); + $start = request_var('start', 0); + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_split'))) + { + return; + } + + $post_id = $post_id_list[0]; + $post_info = get_post_data(array($post_id)); + + if (!sizeof($post_info)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + $post_info = $post_info[$post_id]; + $subject = trim($subject); + + // Make some tests + if (!$subject) + { + $template->assign_var('MESSAGE', $user->lang['EMPTY_SUBJECT']); + return; + } + + if ($to_forum_id <= 0) + { + $template->assign_var('MESSAGE', $user->lang['NO_DESTINATION_FORUM']); + return; + } + + $forum_info = get_forum_data(array($to_forum_id), 'f_post'); + + if (!sizeof($forum_info)) + { + $template->assign_var('MESSAGE', $user->lang['USER_CANNOT_POST']); + return; + } + + $forum_info = $forum_info[$to_forum_id]; + + if ($forum_info['forum_type'] != FORUM_POST) + { + $template->assign_var('MESSAGE', $user->lang['FORUM_NOT_POSTABLE']); + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'post_id_list' => $post_id_list, + 'f' => $forum_id, + 'mode' => 'topic_view', + 'start' => $start, + 'action' => $action, + 't' => $topic_id, + 'redirect' => $redirect, + 'subject' => $subject, + 'to_forum_id' => $to_forum_id, + 'icon' => request_var('icon', 0)) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + if ($action == 'split_beyond') + { + $sort_days = $total = 0; + $sort_key = $sort_dir = ''; + $sort_by_sql = $sort_order_sql = array(); + mcp_sorting('viewtopic', $sort_days, $sort_key, $sort_dir, $sort_by_sql, $sort_order_sql, $total, $forum_id, $topic_id); + + $limit_time_sql = ($sort_days) ? 'AND t.topic_last_post_time >= ' . (time() - ($sort_days * 86400)) : ''; + + if ($sort_order_sql[0] == 'u') + { + $sql = 'SELECT p.post_id, p.forum_id, p.post_approved + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u + WHERE p.topic_id = $topic_id + AND p.poster_id = u.user_id + $limit_time_sql + ORDER BY $sort_order_sql"; + } + else + { + $sql = 'SELECT p.post_id, p.forum_id, p.post_approved + FROM ' . POSTS_TABLE . " p + WHERE p.topic_id = $topic_id + $limit_time_sql + ORDER BY $sort_order_sql"; + } + $result = $db->sql_query_limit($sql, 0, $start); + + $store = false; + $post_id_list = array(); + while ($row = $db->sql_fetchrow($result)) + { + // If split from selected post (split_beyond), we split the unapproved items too. + if (!$row['post_approved'] && !$auth->acl_get('m_approve', $row['forum_id'])) + { +// continue; + } + + // Start to store post_ids as soon as we see the first post that was selected + if ($row['post_id'] == $post_id) + { + $store = true; + } + + if ($store) + { + $post_id_list[] = $row['post_id']; + } + } + $db->sql_freeresult($result); + } + + if (!sizeof($post_id_list)) + { + trigger_error('NO_POST_SELECTED'); + } + + $icon_id = request_var('icon', 0); + + $sql_ary = array( + 'forum_id' => $to_forum_id, + 'topic_title' => $subject, + 'icon_id' => $icon_id, + 'topic_approved'=> 1 + ); + + $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary); + $db->sql_query($sql); + + $to_topic_id = $db->sql_nextid(); + move_posts($post_id_list, $to_topic_id); + + $topic_info = get_topic_data(array($topic_id)); + $topic_info = $topic_info[$topic_id]; + + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_SPLIT_DESTINATION', $subject); + add_log('mod', $forum_id, $topic_id, 'LOG_SPLIT_SOURCE', $topic_info['topic_title']); + + // Change topic title of first post + $sql = 'UPDATE ' . POSTS_TABLE . " + SET post_subject = '" . $db->sql_escape($subject) . "' + WHERE post_id = {$post_id_list[0]}"; + $db->sql_query($sql); + + $success_msg = 'TOPIC_SPLIT_SUCCESS'; + + // Update forum statistics + set_config('num_topics', $config['num_topics'] + 1, true); + + // Link back to both topics + $return_link = sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', 'f=' . $post_info['forum_id'] . '&t=' . $post_info['topic_id']) . '">', '</a>') . '<br /><br />' . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid('viewtopic', 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, ($action == 'split_all') ? 'SPLIT_TOPIC_ALL' : 'SPLIT_TOPIC_BEYOND', $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid('viewtopic', "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +/** +* Merge selected posts into selected topic +*/ +function merge_posts($topic_id, $to_topic_id) +{ + global $db, $template, $user, $auth; + + if (!$to_topic_id) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = get_topic_data(array($to_topic_id), 'm_merge'); + + if (!sizeof($topic_data)) + { + $template->assign_var('MESSAGE', $user->lang['NO_FINAL_TOPIC_SELECTED']); + return; + } + + $topic_data = $topic_data[$to_topic_id]; + + $post_id_list = request_var('post_id_list', array(0)); + $start = request_var('start', 0); + + if (!sizeof($post_id_list)) + { + $template->assign_var('MESSAGE', $user->lang['NO_POST_SELECTED']); + return; + } + + if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_merge'))) + { + return; + } + + $redirect = request_var('redirect', build_url(array('quickmod'))); + + $s_hidden_fields = build_hidden_fields(array( + 'i' => 'main', + 'post_id_list' => $post_id_list, + 'to_topic_id' => $to_topic_id, + 'mode' => 'topic_view', + 'action' => 'merge_posts', + 'start' => $start, + 'redirect' => $redirect, + 't' => $topic_id) + ); + $success_msg = $return_link = ''; + + if (confirm_box(true)) + { + $to_forum_id = $topic_data['forum_id']; + + move_posts($post_id_list, $to_topic_id); + add_log('mod', $to_forum_id, $to_topic_id, 'LOG_MERGE', $topic_data['topic_title']); + + // Message and return links + $success_msg = 'POSTS_MERGED_SUCCESS'; + + // Does the original topic still exist? If yes, link back to it + $sql = 'SELECT forum_id + FROM ' . TOPICS_TABLE . ' + WHERE topic_id = ' . $topic_id; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $return_link .= sprintf($user->lang['RETURN_TOPIC'], '<a href="' . append_sid('viewtopic', 'f=' . $row['forum_id'] . '&t=' . $topic_id) . '">', '</a>'); + } + else + { + // If the topic no longer exist, we will update the topic watch table. + // To not let it error out on users watching both topics, we just return on an error... + $db->sql_return_on_error(true); + $db->sql_query('UPDATE ' . TOPICS_WATCH_TABLE . ' SET topic_id = ' . (int) $to_topic_id . ' WHERE topic_id = ' . (int) $topic_id); + $db->sql_return_on_error(false); + + $db->sql_query('DELETE FROM ' . TOPICS_WATCH_TABLE . ' WHERE topic_id = ' . (int) $topic_id); + } + + // Link to the new topic + $return_link .= (($return_link) ? '<br /><br />' : '') . sprintf($user->lang['RETURN_NEW_TOPIC'], '<a href="' . append_sid('viewtopic', 'f=' . $to_forum_id . '&t=' . $to_topic_id) . '">', '</a>'); + } + else + { + confirm_box(false, 'MERGE_POSTS', $s_hidden_fields); + } + + $redirect = request_var('redirect', 'index.' . PHP_EXT); + $redirect = reapply_sid($redirect); + + if (!$success_msg) + { + return; + } + else + { + meta_refresh(3, append_sid('viewtopic', "f=$to_forum_id&t=$to_topic_id")); + trigger_error($user->lang[$success_msg] . '<br /><br />' . $return_link); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/mcp/mcp_warn.php b/phpBB/modules/mcp/mcp_warn.php new file mode 100644 index 0000000000..d989254e15 --- /dev/null +++ b/phpBB/modules/mcp/mcp_warn.php @@ -0,0 +1,503 @@ +<?php +/** +* +* @package mcp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* mcp_warn +* Handling warning the users +* @package mcp +*/ +class mcp_warn +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $auth, $db, $user, $template, $config; + + $action = request_var('action', array('' => '')); + + if (is_array($action)) + { + list($action, ) = each($action); + } + + $this->page_title = 'MCP_WARN'; + + add_form_key('mcp_warn'); + + switch ($mode) + { + case 'front': + $this->mcp_warn_front_view(); + $this->tpl_name = 'mcp_warn_front'; + break; + + case 'list': + $this->mcp_warn_list_view($action); + $this->tpl_name = 'mcp_warn_list'; + break; + + case 'warn_post': + $this->mcp_warn_post_view($action); + $this->tpl_name = 'mcp_warn_post'; + break; + + case 'warn_user': + $this->mcp_warn_user_view($action); + $this->tpl_name = 'mcp_warn_user'; + break; + } + } + + /** + * Generates the summary on the main page of the warning module + */ + function mcp_warn_front_view() + { + global $template, $db, $user, $auth, $config; + + $template->assign_vars(array( + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=mcp&field=username&select_single=true'), + 'U_POST_ACTION' => append_sid('mcp', 'i=warn&mode=warn_user'), + )); + + // Obtain a list of the 5 naughtiest users.... + // These are the 5 users with the highest warning count + $highest = array(); + $count = 0; + + view_warned_users($highest, $count, 5); + + foreach ($highest as $row) + { + $template->assign_block_vars('highest', array( + 'U_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid('memberlist', 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['user_last_warning']), + 'WARNINGS' => $row['user_warnings'], + )); + } + + // And now the 5 most recent users to get in trouble + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_warnings, w.warning_time + FROM ' . USERS_TABLE . ' u, ' . WARNINGS_TABLE . ' w + WHERE u.user_id = w.user_id + ORDER BY w.warning_time DESC'; + $result = $db->sql_query_limit($sql, 5); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('latest', array( + 'U_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid('memberlist', 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['warning_time']), + 'WARNINGS' => $row['user_warnings'], + )); + } + $db->sql_freeresult($result); + } + + /** + * Lists all users with warnings + */ + function mcp_warn_list_view($action) + { + global $template, $db, $user, $auth, $config; + + $user->add_lang('memberlist'); + + $start = request_var('start', 0); + $st = request_var('st', 0); + $sk = request_var('sk', 'b'); + $sd = request_var('sd', 'd'); + + $limit_days = array(0 => $user->lang['ALL_ENTRIES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + $sort_by_text = array('a' => $user->lang['SORT_USERNAME'], 'b' => $user->lang['SORT_DATE'], 'c' => $user->lang['SORT_WARNINGS']); + $sort_by_sql = array('a' => 'username_clean', 'b' => 'user_last_warning', 'c' => 'user_warnings'); + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $st, $sk, $sd, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + // Define where and sort sql for use in displaying logs + $sql_where = ($st) ? (time() - ($st * 86400)) : 0; + $sql_sort = $sort_by_sql[$sk] . ' ' . (($sd == 'd') ? 'DESC' : 'ASC'); + + $users = array(); + $user_count = 0; + + view_warned_users($users, $user_count, $config['topics_per_page'], $start, $sql_where, $sql_sort); + + foreach ($users as $row) + { + $template->assign_block_vars('user', array( + 'U_NOTES' => append_sid('mcp', 'i=notes&mode=user_notes&u=' . $row['user_id']), + + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => ($row['user_colour']) ? '#' . $row['user_colour'] : '', + 'U_USER' => append_sid('memberlist', 'mode=viewprofile&u=' . $row['user_id']), + + 'WARNING_TIME' => $user->format_date($row['user_last_warning']), + 'WARNINGS' => $row['user_warnings'], + )); + } + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + 'S_CLEAR_ALLOWED' => ($auth->acl_get('a_clearlogs')) ? true : false, + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + + 'PAGE_NUMBER' => on_page($user_count, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination(append_sid('mcp', "i=warn&mode=list&st=$st&sk=$sk&sd=$sd"), $user_count, $config['topics_per_page'], $start), + 'TOTAL_USERS' => ($user_count == 1) ? $user->lang['LIST_USER'] : sprintf($user->lang['LIST_USERS'], $user_count), + )); + } + + /** + * Handles warning the user when the warning is for a specific post + */ + function mcp_warn_post_view($action) + { + global $template, $db, $user, $auth, $config; + + $post_id = request_var('p', 0); + $forum_id = request_var('f', 0); + $notify = request::is_set('notify_user'); + $warning = utf8_normalize_nfc(request_var('warning', '', true)); + + $sql = 'SELECT u.*, p.* + FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u + WHERE post_id = $post_id + AND u.user_id = p.poster_id"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_POST'); + } + + // There is no point issuing a warning to ignored users (ie anonymous and bots) + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('CANNOT_WARN_ANONYMOUS'); + } + + // Prevent someone from warning themselves + if ($user_row['user_id'] == $user->data['user_id']) + { + trigger_error('CANNOT_WARN_SELF'); + } + + // Check if there is already a warning for this post to prevent multiple + // warnings for the same offence + $sql = 'SELECT post_id + FROM ' . WARNINGS_TABLE . " + WHERE post_id = $post_id"; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error('ALREADY_WARNED'); + } + + $user_id = $user_row['user_id']; + + if (strpos($this->u_action, "&f=$forum_id&p=$post_id") === false) + { + $this->p_master->adjust_url("&f=$forum_id&p=$post_id"); + $this->u_action .= "&f=$forum_id&p=$post_id"; + } + + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + + if ($warning && $action == 'add_warning') + { + if (check_form_key('mcp_warn')) + { + add_warning($user_row, $warning, $notify, $post_id); + $msg = $user->lang['USER_WARNING_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = append_sid('mcp', "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // OK, they didn't submit a warning so lets build the page for them to do so + + // We want to make the message available here as a reminder + // Parse the message and subject + $message = censor_text($user_row['post_text']); + + // Second parse bbcode here + if ($user_row['bbcode_bitfield']) + { + include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + + $bbcode = new bbcode($user_row['bbcode_bitfield']); + $bbcode->bbcode_second_pass($message, $user_row['bbcode_uid'], $user_row['bbcode_bitfield']); + } + + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); + + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + + 'POST' => $message, + 'USERNAME' => $user_row['username'], + 'USER_COLOR' => (!empty($user_row['user_colour'])) ? $user_row['user_colour'] : '', + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($user_row['user_regdate']), + 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, + 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + + 'L_WARNING_POST_DEFAULT' => sprintf($user->lang['WARNING_POST_DEFAULT'], generate_board_url() . '/viewtopic.' . PHP_EXT . "?f=$forum_id&p=$post_id#p$post_id"), + + 'S_CAN_NOTIFY' => $s_can_notify, + )); + } + + /** + * Handles warning the user + */ + function mcp_warn_user_view($action) + { + global $config, $module; + global $template, $db, $user, $auth; + + $user_id = request_var('u', 0); + $username = request_var('username', '', true); + $notify = request::is_set('notify_user'); + $warning = utf8_normalize_nfc(request_var('warning', '', true)); + + $sql_where = ($user_id) ? "user_id = $user_id" : "username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE ' . $sql_where; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_USER'); + } + + // Prevent someone from warning themselves + if ($user_row['user_id'] == $user->data['user_id']) + { + trigger_error('CANNOT_WARN_SELF'); + } + + $user_id = $user_row['user_id']; + + if (strpos($this->u_action, "&u=$user_id") === false) + { + $this->p_master->adjust_url('&u=' . $user_id); + $this->u_action .= "&u=$user_id"; + } + + // Check if can send a notification + if ($config['allow_privmsg']) + { + $auth2 = new auth(); + $auth2->acl($user_row); + $s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false; + unset($auth2); + } + else + { + $s_can_notify = false; + } + + // Prevent against clever people + if ($notify && !$s_can_notify) + { + $notify = false; + } + + if ($warning && $action == 'add_warning') + { + if (check_form_key('mcp_warn')) + { + add_warning($user_row, $warning, $notify); + $msg = $user->lang['USER_WARNING_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $redirect = append_sid('mcp', "i=notes&mode=user_notes&u=$user_id"); + meta_refresh(2, $redirect); + trigger_error($msg . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $redirect . '">', '</a>')); + } + + // Generate the appropriate user information for the user we are looking at + if (!function_exists('get_user_avatar')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + } + + $rank_title = $rank_img = ''; + $avatar_img = get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']); + + // OK, they didn't submit a warning so lets build the page for them to do so + $template->assign_vars(array( + 'U_POST_ACTION' => $this->u_action, + + 'USERNAME' => $user_row['username'], + 'USER_COLOR' => (!empty($user_row['user_colour'])) ? $user_row['user_colour'] : '', + 'RANK_TITLE' => $rank_title, + 'JOINED' => $user->format_date($user_row['user_regdate']), + 'POSTS' => ($user_row['user_posts']) ? $user_row['user_posts'] : 0, + 'WARNINGS' => ($user_row['user_warnings']) ? $user_row['user_warnings'] : 0, + + 'AVATAR_IMG' => $avatar_img, + 'RANK_IMG' => $rank_img, + + 'S_CAN_NOTIFY' => $s_can_notify, + )); + + return $user_id; + } +} + +/** +* Insert the warning into the database +*/ +function add_warning($user_row, $warning, $send_pm = true, $post_id = 0) +{ + global $template, $db, $user, $auth, $config; + + if ($send_pm) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_privmsgs.' . PHP_EXT); + include_once(PHPBB_ROOT_PATH . 'includes/message_parser.' . PHP_EXT); + + $user_row['user_lang'] = (file_exists(PHPBB_ROOT_PATH . 'language/' . $user_row['user_lang'] . '/mcp.' . PHP_EXT)) ? $user_row['user_lang'] : $config['default_lang']; + include(PHPBB_ROOT_PATH . 'language/' . basename($user_row['user_lang']) . '/mcp.' . PHP_EXT); + + $message_parser = new parse_message(); + + $message_parser->message = sprintf($lang['WARNING_PM_BODY'], $warning); + $message_parser->parse(true, true, true, false, false, true, true); + + $pm_data = array( + 'from_user_id' => $user->data['user_id'], + 'from_user_ip' => $user->ip, + 'from_username' => $user->data['username'], + 'enable_sig' => false, + 'enable_bbcode' => true, + 'enable_smilies' => true, + 'enable_urls' => false, + 'icon_id' => 0, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, + 'bbcode_uid' => $message_parser->bbcode_uid, + 'message' => $message_parser->message, + 'address_list' => array('u' => array($user_row['user_id'] => 'to')), + ); + + submit_pm('post', $lang['WARNING_PM_SUBJECT'], $pm_data, false); + } + + add_log('admin', 'LOG_USER_WARNING', $user_row['username']); + $log_id = add_log('user', $user_row['user_id'], 'LOG_USER_WARNING_BODY', $warning); + + $sql_ary = array( + 'user_id' => $user_row['user_id'], + 'post_id' => $post_id, + 'log_id' => $log_id, + 'warning_time' => time(), + ); + + $db->sql_query('INSERT INTO ' . WARNINGS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary)); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_warnings = user_warnings + 1, + user_last_warning = ' . time() . ' + WHERE user_id = ' . $user_row['user_id']; + $db->sql_query($sql); + + // We add this to the mod log too for moderators to see that a specific user got warned. + $sql = 'SELECT forum_id, topic_id + FROM ' . POSTS_TABLE . ' + WHERE post_id = ' . $post_id; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + add_log('mod', $row['forum_id'], $row['topic_id'], 'LOG_USER_WARNING', $user_row['username']); +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_attachments.php b/phpBB/modules/ucp/info/ucp_attachments.php new file mode 100644 index 0000000000..84edce446c --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_attachments.php @@ -0,0 +1,37 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_attachments_info +{ + function module() + { + return array( + 'filename' => 'ucp_attachments', + 'title' => 'UCP_ATTACHMENTS', + 'version' => '1.0.0', + 'modes' => array( + 'attachments' => array('title' => 'UCP_MAIN_ATTACHMENTS', 'auth' => 'acl_u_attach', 'cat' => array('UCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_groups.php b/phpBB/modules/ucp/info/ucp_groups.php new file mode 100644 index 0000000000..2002123c50 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_groups.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_groups_info +{ + function module() + { + return array( + 'filename' => 'ucp_groups', + 'title' => 'UCP_USERGROUPS', + 'version' => '1.0.0', + 'modes' => array( + 'membership' => array('title' => 'UCP_USERGROUPS_MEMBER', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), + 'manage' => array('title' => 'UCP_USERGROUPS_MANAGE', 'auth' => '', 'cat' => array('UCP_USERGROUPS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_main.php b/phpBB/modules/ucp/info/ucp_main.php new file mode 100644 index 0000000000..722b7865e6 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_main.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_main_info +{ + function module() + { + return array( + 'filename' => 'ucp_main', + 'title' => 'UCP_MAIN', + 'version' => '1.0.0', + 'modes' => array( + 'front' => array('title' => 'UCP_MAIN_FRONT', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'subscribed' => array('title' => 'UCP_MAIN_SUBSCRIBED', 'auth' => '', 'cat' => array('UCP_MAIN')), + 'bookmarks' => array('title' => 'UCP_MAIN_BOOKMARKS', 'auth' => 'cfg_allow_bookmarks', 'cat' => array('UCP_MAIN')), + 'drafts' => array('title' => 'UCP_MAIN_DRAFTS', 'auth' => '', 'cat' => array('UCP_MAIN')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_pm.php b/phpBB/modules/ucp/info/ucp_pm.php new file mode 100644 index 0000000000..ade12005c0 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_pm.php @@ -0,0 +1,40 @@ +<?php +/** +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_pm_info +{ + function module() + { + return array( + 'filename' => 'ucp_pm', + 'title' => 'UCP_PM', + 'version' => '1.0.0', + 'modes' => array( + 'view' => array('title' => 'UCP_PM_VIEW', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), + 'compose' => array('title' => 'UCP_PM_COMPOSE', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'drafts' => array('title' => 'UCP_PM_DRAFTS', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'options' => array('title' => 'UCP_PM_OPTIONS', 'auth' => 'cfg_allow_privmsg', 'cat' => array('UCP_PM')), + 'popup' => array('title' => 'UCP_PM_POPUP_TITLE', 'auth' => 'cfg_allow_privmsg', 'display' => false, 'cat' => array('UCP_PM')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_prefs.php b/phpBB/modules/ucp/info/ucp_prefs.php new file mode 100644 index 0000000000..58359e8a19 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_prefs.php @@ -0,0 +1,39 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_prefs_info +{ + function module() + { + return array( + 'filename' => 'ucp_prefs', + 'title' => 'UCP_PREFS', + 'version' => '1.0.0', + 'modes' => array( + 'personal' => array('title' => 'UCP_PREFS_PERSONAL', 'auth' => '', 'cat' => array('UCP_PREFS')), + 'post' => array('title' => 'UCP_PREFS_POST', 'auth' => '', 'cat' => array('UCP_PREFS')), + 'view' => array('title' => 'UCP_PREFS_VIEW', 'auth' => '', 'cat' => array('UCP_PREFS')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_profile.php b/phpBB/modules/ucp/info/ucp_profile.php new file mode 100644 index 0000000000..03a4c81f46 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_profile.php @@ -0,0 +1,40 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_profile_info +{ + function module() + { + return array( + 'filename' => 'ucp_profile', + 'title' => 'UCP_PROFILE', + 'version' => '1.0.0', + 'modes' => array( + 'profile_info' => array('title' => 'UCP_PROFILE_PROFILE_INFO', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'signature' => array('title' => 'UCP_PROFILE_SIGNATURE', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'avatar' => array('title' => 'UCP_PROFILE_AVATAR', 'auth' => '', 'cat' => array('UCP_PROFILE')), + 'reg_details' => array('title' => 'UCP_PROFILE_REG_DETAILS', 'auth' => '', 'cat' => array('UCP_PROFILE')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/info/ucp_zebra.php b/phpBB/modules/ucp/info/ucp_zebra.php new file mode 100644 index 0000000000..5fc1f8bee7 --- /dev/null +++ b/phpBB/modules/ucp/info/ucp_zebra.php @@ -0,0 +1,38 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @package module_install +*/ +class ucp_zebra_info +{ + function module() + { + return array( + 'filename' => 'ucp_zebra', + 'title' => 'UCP_ZEBRA', + 'version' => '1.0.0', + 'modes' => array( + 'friends' => array('title' => 'UCP_ZEBRA_FRIENDS', 'auth' => '', 'cat' => array('UCP_ZEBRA')), + 'foes' => array('title' => 'UCP_ZEBRA_FOES', 'auth' => '', 'cat' => array('UCP_ZEBRA')), + ), + ); + } + + function install() + { + } + + function uninstall() + { + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_activate.php b/phpBB/modules/ucp/ucp_activate.php new file mode 100644 index 0000000000..594e346310 --- /dev/null +++ b/phpBB/modules/ucp/ucp_activate.php @@ -0,0 +1,128 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_activate +* User activation +* @package ucp +*/ +class ucp_activate +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $user_id = request_var('u', 0); + $key = request_var('k', ''); + + $sql = 'SELECT user_id, username, user_type, user_email, user_newpasswd, user_lang, user_notify_type, user_actkey, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_id = $user_id"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_USER'); + } + + if ($user_row['user_type'] <> USER_INACTIVE && !$user_row['user_newpasswd']) + { + meta_refresh(3, append_sid('index')); + trigger_error('ALREADY_ACTIVATED'); + } + + if (($user_row['user_inactive_reason'] == INACTIVE_MANUAL) || $user_row['user_actkey'] != $key) + { + trigger_error('WRONG_ACTIVATION'); + } + + $update_password = ($user_row['user_newpasswd']) ? true : false; + + if ($update_password) + { + $sql_ary = array( + 'user_actkey' => '', + 'user_password' => $user_row['user_newpasswd'], + 'user_newpasswd' => '', + 'user_pass_convert' => 0, + 'user_login_attempts' => 0, + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user_row['user_id']; + $db->sql_query($sql); + } + + if (!$update_password) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); + + user_active_flip('activate', $user_row['user_id']); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_actkey = '' + WHERE user_id = {$user_row['user_id']}"; + $db->sql_query($sql); + } + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN && !$update_password) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $messenger = new messenger(false); + + $messenger->template('admin_welcome_activated', $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username'])) + ); + + $messenger->send($user_row['user_notify_type']); + + $message = 'ACCOUNT_ACTIVE_ADMIN'; + } + else + { + if (!$update_password) + { + $message = ($user_row['user_inactive_reason'] == INACTIVE_PROFILE) ? 'ACCOUNT_ACTIVE_PROFILE' : 'ACCOUNT_ACTIVE'; + } + else + { + $message = 'PASSWORD_ACTIVATED'; + } + } + + meta_refresh(3, append_sid('index')); + trigger_error($user->lang[$message]); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_attachments.php b/phpBB/modules/ucp/ucp_attachments.php new file mode 100644 index 0000000000..39fbe84ae1 --- /dev/null +++ b/phpBB/modules/ucp/ucp_attachments.php @@ -0,0 +1,201 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_attachments +* User attachments +* @package ucp +*/ +class ucp_attachments +{ + var $u_action; + + function main($id, $mode) + { + global $template, $user, $db, $config; + + $start = request_var('start', 0); + $sort_key = request_var('sk', 'a'); + $sort_dir = request_var('sd', 'a'); + + $delete = request::is_set_post('delete'); + $confirm = request::is_set_post('confirm'); + $delete_ids = array_keys(request_var('attachment', array(0))); + + if ($delete && sizeof($delete_ids)) + { + // Validate $delete_ids... + $sql = 'SELECT attach_id + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user->data['user_id'] . ' + AND is_orphan = 0 + AND ' . $db->sql_in_set('attach_id', $delete_ids); + $result = $db->sql_query($sql); + + $delete_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $delete_ids[] = $row['attach_id']; + } + $db->sql_freeresult($result); + } + + if ($delete && sizeof($delete_ids)) + { + $s_hidden_fields = array( + 'delete' => 1 + ); + + foreach ($delete_ids as $attachment_id) + { + $s_hidden_fields['attachment'][$attachment_id] = 1; + } + + if (confirm_box(true)) + { + if (!function_exists('delete_attachments')) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); + } + + delete_attachments('attach', $delete_ids); + + meta_refresh(3, $this->u_action); + $message = ((sizeof($delete_ids) == 1) ? $user->lang['ATTACHMENT_DELETED'] : $user->lang['ATTACHMENTS_DELETED']) . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, (sizeof($delete_ids) == 1) ? 'DELETE_ATTACHMENT' : 'DELETE_ATTACHMENTS', build_hidden_fields($s_hidden_fields)); + } + } + + // Select box eventually + $sort_key_text = array('a' => $user->lang['SORT_FILENAME'], 'b' => $user->lang['SORT_COMMENT'], 'c' => $user->lang['SORT_EXTENSION'], 'd' => $user->lang['SORT_SIZE'], 'e' => $user->lang['SORT_DOWNLOADS'], 'f' => $user->lang['SORT_POST_TIME'], 'g' => $user->lang['SORT_TOPIC_TITLE']); + $sort_key_sql = array('a' => 'a.real_filename', 'b' => 'a.attach_comment', 'c' => 'a.extension', 'd' => 'a.filesize', 'e' => 'a.download_count', 'f' => 'a.filetime', 'g' => 't.topic_title'); + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + $s_sort_key = ''; + foreach ($sort_key_text as $key => $value) + { + $selected = ($sort_key == $key) ? ' selected="selected"' : ''; + $s_sort_key .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + $s_sort_dir = ''; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($sort_dir == $key) ? ' selected="selected"' : ''; + $s_sort_dir .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + + if (!isset($sort_key_sql[$sort_key])) + { + $sort_key = 'a'; + } + + $order_by = $sort_key_sql[$sort_key] . ' ' . (($sort_dir == 'a') ? 'ASC' : 'DESC'); + + $sql = 'SELECT COUNT(attach_id) as num_attachments + FROM ' . ATTACHMENTS_TABLE . ' + WHERE poster_id = ' . $user->data['user_id'] . ' + AND is_orphan = 0'; + $result = $db->sql_query($sql); + $num_attachments = $db->sql_fetchfield('num_attachments'); + $db->sql_freeresult($result); + + $sql = 'SELECT a.*, t.topic_title, p.message_subject as message_title + FROM ' . ATTACHMENTS_TABLE . ' a + LEFT JOIN ' . TOPICS_TABLE . ' t ON (a.topic_id = t.topic_id AND a.in_message = 0) + LEFT JOIN ' . PRIVMSGS_TABLE . ' p ON (a.post_msg_id = p.msg_id AND a.in_message = 1) + WHERE a.poster_id = ' . $user->data['user_id'] . " + AND a.is_orphan = 0 + ORDER BY $order_by"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $row_count = 0; + if ($row = $db->sql_fetchrow($result)) + { + $template->assign_var('S_ATTACHMENT_ROWS', true); + + do + { + if ($row['in_message']) + { + $view_topic = append_sid('ucp', "i=pm&p={$row['post_msg_id']}"); + } + else + { + $view_topic = append_sid('viewtopic', "t={$row['topic_id']}&p={$row['post_msg_id']}") . "#p{$row['post_msg_id']}"; + } + + $template->assign_block_vars('attachrow', array( + 'ROW_NUMBER' => $row_count + ($start + 1), + 'FILENAME' => $row['real_filename'], + 'COMMENT' => bbcode_nl2br($row['attach_comment']), + 'EXTENSION' => $row['extension'], + 'SIZE' => get_formatted_filesize($row['filesize']), + 'DOWNLOAD_COUNT' => $row['download_count'], + 'POST_TIME' => $user->format_date($row['filetime']), + 'TOPIC_TITLE' => ($row['in_message']) ? $row['message_title'] : $row['topic_title'], + + 'ATTACH_ID' => $row['attach_id'], + 'POST_ID' => $row['post_msg_id'], + 'TOPIC_ID' => $row['topic_id'], + + 'S_IN_MESSAGE' => $row['in_message'], + + 'U_VIEW_ATTACHMENT' => append_sid('download/file', 'id=' . $row['attach_id']), + 'U_VIEW_TOPIC' => $view_topic) + ); + + $row_count++; + } + while ($row = $db->sql_fetchrow($result)); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'PAGE_NUMBER' => on_page($num_attachments, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&sk=$sort_key&sd=$sort_dir", $num_attachments, $config['topics_per_page'], $start), + 'TOTAL_ATTACHMENTS' => $num_attachments, + + 'L_TITLE' => $user->lang['UCP_ATTACHMENTS'], + + 'U_SORT_FILENAME' => $this->u_action . "&sk=a&sd=" . (($sort_key == 'a' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_FILE_COMMENT' => $this->u_action . "&sk=b&sd=" . (($sort_key == 'b' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_EXTENSION' => $this->u_action . "&sk=c&sd=" . (($sort_key == 'c' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_FILESIZE' => $this->u_action . "&sk=d&sd=" . (($sort_key == 'd' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_DOWNLOADS' => $this->u_action . "&sk=e&sd=" . (($sort_key == 'e' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_POST_TIME' => $this->u_action . "&sk=f&sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'), + 'U_SORT_TOPIC_TITLE' => $this->u_action . "&sk=g&sd=" . (($sort_key == 'f' && $sort_dir == 'a') ? 'd' : 'a'), + + 'S_DISPLAY_MARK_ALL' => ($num_attachments) ? true : false, + 'S_DISPLAY_PAGINATION' => ($num_attachments) ? true : false, + 'S_UCP_ACTION' => $this->u_action, + 'S_SORT_OPTIONS' => $s_sort_key, + 'S_ORDER_SELECT' => $s_sort_dir) + ); + + $this->tpl_name = 'ucp_attachments'; + $this->page_title = 'UCP_ATTACHMENTS'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_confirm.php b/phpBB/modules/ucp/ucp_confirm.php new file mode 100644 index 0000000000..26ffc3c5fb --- /dev/null +++ b/phpBB/modules/ucp/ucp_confirm.php @@ -0,0 +1,48 @@ +<?php +/** +* +* @package VC +* @version $Id$ +* @copyright (c) 2005 2008 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_confirm +* Visual confirmation +* +* Note to potential users of this code ... +* +* Remember this is released under the _GPL_ and is subject +* to that licence. Do not incorporate this within software +* released or distributed in any way under a licence other +* than the GPL. We will be watching ... ;) +* +* @package VC +*/ +class ucp_confirm +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $config; + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(request_var('type', 0)); + $captcha->execute(); + garbage_collection(); + exit_handler(); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_groups.php b/phpBB/modules/ucp/ucp_groups.php new file mode 100644 index 0000000000..3dd80fb813 --- /dev/null +++ b/phpBB/modules/ucp/ucp_groups.php @@ -0,0 +1,1089 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_groups +* @package ucp +*/ +class ucp_groups +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $cache, $template, $config; + + $user->add_lang('groups'); + + $return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>'); + + $mark_ary = request_var('mark', array(0)); + $submit = request::variable('submit', false, false, request::POST); + $delete = request::variable('delete', false, false, request::POST); + $error = $data = array(); + + switch ($mode) + { + case 'membership': + + $this->page_title = 'UCP_USERGROUPS_MEMBER'; + + if ($submit || request::is_set_post('change_default')) + { + $action = (request::is_set_post('change_default')) ? 'change_default' : request_var('action', ''); + $group_id = ($action == 'change_default') ? request_var('default', 0) : request_var('selected', 0); + + if (!$group_id) + { + trigger_error('NO_GROUP_SELECTED'); + } + + $sql = 'SELECT group_id, group_name, group_type + FROM ' . GROUPS_TABLE . " + WHERE group_id IN ($group_id, {$user->data['group_id']})"; + $result = $db->sql_query($sql); + + $group_row = array(); + while ($row = $db->sql_fetchrow($result)) + { + $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']; + $group_row[$row['group_id']] = $row; + } + $db->sql_freeresult($result); + + if (!sizeof($group_row)) + { + trigger_error('GROUP_NOT_EXIST'); + } + + switch ($action) + { + case 'change_default': + // User already having this group set as default? + if ($group_id == $user->data['group_id']) + { + trigger_error($user->lang['ALREADY_DEFAULT_GROUP'] . $return_page); + } + + if (!$auth->acl_get('u_chggrp')) + { + trigger_error($user->lang['NOT_AUTHORISED'] . $return_page); + } + + // User needs to be member of the group in order to make it default + if (!group_memberships($group_id, $user->data['user_id'], true)) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_attributes('default', $group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_CHANGE', sprintf($user->lang['USER_GROUP_CHANGE'], $group_row[$user->data['group_id']]['group_name'], $group_row[$group_id]['group_name'])); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang['CHANGED_DEFAULT_GROUP'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'default' => $group_id, + 'change_default'=> true + ); + + confirm_box(false, sprintf($user->lang['GROUP_CHANGE_DEFAULT'], $group_row[$group_id]['group_name']), build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'resign': + + // User tries to resign from default group but is not allowed to change it? + if ($group_id == $user->data['group_id'] && !$auth->acl_get('u_chggrp')) + { + trigger_error($user->lang['NOT_RESIGN_FROM_DEFAULT_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + $sql = 'SELECT group_type + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $group_id; + $result = $db->sql_query($sql); + $group_type = (int) $db->sql_fetchfield('group_type'); + $db->sql_freeresult($result); + + if ($group_type != GROUP_OPEN && $group_type != GROUP_FREE) + { + trigger_error($user->lang['CANNOT_RESIGN_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_del($group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_RESIGN', $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang[($row['user_pending']) ? 'GROUP_RESIGNED_PENDING' : 'GROUP_RESIGNED_MEMBERSHIP'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'resign', + 'submit' => true + ); + + confirm_box(false, ($row['user_pending']) ? 'GROUP_RESIGN_PENDING' : 'GROUP_RESIGN_MEMBERSHIP', build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'join': + + $sql = 'SELECT ug.*, u.username, u.username_clean, u.user_email + FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u + WHERE ug.user_id = u.user_id + AND ug.group_id = ' . $group_id . ' + AND ug.user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + if ($row['user_pending']) + { + trigger_error($user->lang['ALREADY_IN_GROUP_PENDING'] . $return_page); + } + + trigger_error($user->lang['ALREADY_IN_GROUP'] . $return_page); + } + + // Check permission to join (open group or request) + if ($group_row[$group_id]['group_type'] != GROUP_OPEN && $group_row[$group_id]['group_type'] != GROUP_FREE) + { + trigger_error($user->lang['CANNOT_JOIN_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + if ($group_row[$group_id]['group_type'] == GROUP_FREE) + { + group_user_add($group_id, $user->data['user_id']); + + $email_template = 'group_added'; + } + else + { + group_user_add($group_id, $user->data['user_id'], false, false, false, 0, 1); + + $email_template = 'group_request'; + } + + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + $messenger = new messenger(); + + $sql = 'SELECT u.username, u.username_clean, u.user_email, u.user_notify_type, u.user_jabber, u.user_lang + FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u + WHERE ug.user_id = u.user_id + AND ' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? "ug.user_id = {$user->data['user_id']}" : 'ug.group_leader = 1') . " + AND ug.group_id = $group_id"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template($email_template, $row['user_lang']); + + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($row['username']), + 'GROUP_NAME' => htmlspecialchars_decode($group_row[$group_id]['group_name']), + 'REQUEST_USERNAME' => $user->data['username'], + + 'U_PENDING' => generate_board_url() . '/ucp.' . PHP_EXT . "?i=groups&mode=manage&action=list&g=$group_id", + 'U_GROUP' => generate_board_url() . '/memberlist.' . PHP_EXT . "?mode=group&g=$group_id") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + + $messenger->save_queue(); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_JOIN' . (($group_row[$group_id]['group_type'] == GROUP_FREE) ? '' : '_PENDING'), $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang[($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOINED' : 'GROUP_JOINED_PENDING'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'join', + 'submit' => true + ); + + confirm_box(false, ($group_row[$group_id]['group_type'] == GROUP_FREE) ? 'GROUP_JOIN' : 'GROUP_JOIN_PENDING', build_hidden_fields($s_hidden_fields)); + } + + break; + + case 'demote': + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + if (confirm_box(true)) + { + group_user_attributes('demote', $group_id, $user->data['user_id']); + + add_log('user', $user->data['user_id'], 'LOG_USER_GROUP_DEMOTE', $group_row[$group_id]['group_name']); + + meta_refresh(3, $this->u_action); + trigger_error($user->lang['USER_GROUP_DEMOTED'] . $return_page); + } + else + { + $s_hidden_fields = array( + 'selected' => $group_id, + 'action' => 'demote', + 'submit' => true + ); + + confirm_box(false, 'USER_GROUP_DEMOTE', build_hidden_fields($s_hidden_fields)); + } + + break; + } + } + + $sql = 'SELECT g.*, ug.group_leader, ug.user_pending + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND g.group_id = ug.group_id + ORDER BY g.group_type DESC, g.group_name'; + $result = $db->sql_query($sql); + + $group_id_ary = array(); + + while ($row = $db->sql_fetchrow($result)) + { + $block = ($row['group_leader']) ? 'leader' : (($row['user_pending']) ? 'pending' : 'member'); + + switch ($row['group_type']) + { + case GROUP_OPEN: + $group_status = 'OPEN'; + break; + + case GROUP_CLOSED: + $group_status = 'CLOSED'; + break; + + case GROUP_HIDDEN: + $group_status = 'HIDDEN'; + break; + + case GROUP_SPECIAL: + $group_status = 'SPECIAL'; + break; + + case GROUP_FREE: + $group_status = 'FREE'; + break; + } + + $template->assign_block_vars($block, array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], + 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, + 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], + 'GROUP_COLOUR' => $row['group_colour'], + + 'U_VIEW_GROUP' => append_sid('memberlist', 'mode=group&g=' . $row['group_id']), + + 'S_GROUP_DEFAULT' => ($row['group_id'] == $user->data['group_id']) ? true : false) + ); + + $group_id_ary[] = $row['group_id']; + } + $db->sql_freeresult($result); + + // Hide hidden groups unless user is an admin with group privileges + $sql_and = ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? '<> ' . GROUP_SPECIAL : 'NOT IN (' . GROUP_SPECIAL . ', ' . GROUP_HIDDEN . ')'; + + $sql = 'SELECT group_id, group_name, group_colour, group_desc, group_desc_uid, group_desc_bitfield, group_desc_options, group_type, group_founder_manage + FROM ' . GROUPS_TABLE . ' + WHERE ' . ((sizeof($group_id_ary)) ? $db->sql_in_set('group_id', $group_id_ary, true) . ' AND ' : '') . " + group_type $sql_and + ORDER BY group_type DESC, group_name"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + switch ($row['group_type']) + { + case GROUP_OPEN: + $group_status = 'OPEN'; + break; + + case GROUP_CLOSED: + $group_status = 'CLOSED'; + break; + + case GROUP_HIDDEN: + $group_status = 'HIDDEN'; + break; + + case GROUP_SPECIAL: + $group_status = 'SPECIAL'; + break; + + case GROUP_FREE: + $group_status = 'FREE'; + break; + } + + $template->assign_block_vars('nonmember', array( + 'GROUP_ID' => $row['group_id'], + 'GROUP_NAME' => ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name'], + 'GROUP_DESC' => ($row['group_type'] <> GROUP_SPECIAL) ? generate_text_for_display($row['group_desc'], $row['group_desc_uid'], $row['group_desc_bitfield'], $row['group_desc_options']) : $user->lang['GROUP_IS_SPECIAL'], + 'GROUP_SPECIAL' => ($row['group_type'] <> GROUP_SPECIAL) ? false : true, + 'GROUP_CLOSED' => ($row['group_type'] <> GROUP_CLOSED || $auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? false : true, + 'GROUP_STATUS' => $user->lang['GROUP_IS_' . $group_status], + 'S_CAN_JOIN' => ($row['group_type'] == GROUP_OPEN || $row['group_type'] == GROUP_FREE) ? true : false, + 'GROUP_COLOUR' => $row['group_colour'], + + 'U_VIEW_GROUP' => append_sid('memberlist', 'mode=group&g=' . $row['group_id'])) + ); + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_CHANGE_DEFAULT' => ($auth->acl_get('u_chggrp')) ? true : false, + 'S_LEADER_COUNT' => $leader_count, + 'S_MEMBER_COUNT' => $member_count, + 'S_PENDING_COUNT' => $pending_count, + 'S_NONMEMBER_COUNT' => $nonmember_count, + + 'S_UCP_ACTION' => $this->u_action) + ); + + break; + + case 'manage': + + $this->page_title = 'UCP_USERGROUPS_MANAGE'; + $action = (request::is_set_post('addusers')) ? 'addusers' : request_var('action', ''); + $group_id = request_var('g', 0); + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + add_form_key('ucp_groups'); + + if ($group_id) + { + $sql = 'SELECT * + FROM ' . GROUPS_TABLE . " + WHERE group_id = $group_id"; + $result = $db->sql_query($sql); + $group_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$group_row) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + // Check if the user is allowed to manage this group if set to founder only. + if ($user->data['user_type'] != USER_FOUNDER && $group_row['group_founder_manage']) + { + trigger_error($user->lang['NOT_ALLOWED_MANAGE_GROUP'] . $return_page, E_USER_WARNING); + } + + $group_name = $group_row['group_name']; + $group_type = $group_row['group_type']; + + $avatar_img = (!empty($group_row['group_avatar'])) ? get_user_avatar($group_row['group_avatar'], $group_row['group_avatar_type'], $group_row['group_avatar_width'], $group_row['group_avatar_height'], 'GROUP_AVATAR') : '<img src="' . PHPBB_ROOT_PATH . CONFIG_ADM_FOLDER . '/images/no_avatar.gif" alt="" />'; + + $template->assign_vars(array( + 'GROUP_NAME' => ($group_type == GROUP_SPECIAL) ? $user->lang['G_' . $group_name] : $group_name, + 'GROUP_INTERNAL_NAME' => $group_name, + 'GROUP_COLOUR' => (isset($group_row['group_colour'])) ? $group_row['group_colour'] : '', + 'GROUP_DESC_DISP' => generate_text_for_display($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_bitfield'], $group_row['group_desc_options']), + 'GROUP_TYPE' => $group_row['group_type'], + + 'AVATAR' => $avatar_img, + 'AVATAR_IMAGE' => $avatar_img, + 'AVATAR_WIDTH' => (isset($group_row['group_avatar_width'])) ? $group_row['group_avatar_width'] : '', + 'AVATAR_HEIGHT' => (isset($group_row['group_avatar_height'])) ? $group_row['group_avatar_height'] : '', + )); + } + + switch ($action) + { + case 'edit': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $file_uploads = (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on') ? true : false; + $user->add_lang(array('acp/groups', 'acp/common')); + + $data = $submit_ary = array(); + + $update = request::is_set_post('update'); + + $error = array(); + + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + $can_upload = (file_exists(PHPBB_ROOT_PATH . $config['avatar_path']) && @is_writable(PHPBB_ROOT_PATH . $config['avatar_path']) && $file_uploads) ? true : false; + + // Did we submit? + if ($update) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc = utf8_normalize_nfc(request_var('group_desc', '', true)); + $group_type = request_var('group_type', GROUP_FREE); + + $allow_desc_bbcode = request_var('desc_parse_bbcode', false); + $allow_desc_urls = request_var('desc_parse_urls', false); + $allow_desc_smilies = request_var('desc_parse_smilies', false); + + $submit_ary = array( + 'colour' => request_var('group_colour', ''), + 'rank' => request_var('group_rank', 0), + 'receive_pm' => request::is_set('group_receive_pm') ? 1 : 0, + 'message_limit' => request_var('group_message_limit', 0), + 'max_recipients'=> request_var('group_max_recipients', 0), + ); + + $data['uploadurl'] = request_var('uploadurl', ''); + $data['remotelink'] = request_var('remotelink', ''); + $data['width'] = request_var('width', ''); + $data['height'] = request_var('height', ''); + $delete = request_var('delete', ''); + + if (!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl'] || $data['remotelink']) + { + // Avatar stuff + $var_ary = array( + 'uploadurl' => array('string', true, 5, 255), + 'remotelink' => array('string', true, 5, 255), + 'width' => array('string', true, 1, 3), + 'height' => array('string', true, 1, 3), + ); + + if (!($error = validate_data($data, $var_ary))) + { + $data['user_id'] = "g$group_id"; + + if ((!empty($_FILES['uploadfile']['tmp_name']) || $data['uploadurl']) && $can_upload) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_upload($data, $error); + } + else if ($data['remotelink']) + { + list($submit_ary['avatar_type'], $submit_ary['avatar'], $submit_ary['avatar_width'], $submit_ary['avatar_height']) = avatar_remote($data, $error); + } + } + } + else if ($avatar_select && $config['allow_avatar_local']) + { + // check avatar gallery + if (is_dir(PHPBB_ROOT_PATH . $config['avatar_gallery_path'] . '/' . $category)) + { + $submit_ary['avatar_type'] = AVATAR_GALLERY; + + list($submit_ary['avatar_width'], $submit_ary['avatar_height']) = getimagesize(PHPBB_ROOT_PATH . $config['avatar_gallery_path'] . '/' . $category . '/' . $avatar_select); + $submit_ary['avatar'] = $category . '/' . $avatar_select; + } + } + else if ($delete) + { + $submit_ary['avatar'] = ''; + $submit_ary['avatar_type'] = $submit_ary['avatar_width'] = $submit_ary['avatar_height'] = 0; + } + else if ($data['width'] && $data['height']) + { + // Only update the dimensions? + if ($config['avatar_max_width'] || $config['avatar_max_height']) + { + if ($data['width'] > $config['avatar_max_width'] || $data['height'] > $config['avatar_max_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + + if (!sizeof($error)) + { + if ($config['avatar_min_width'] || $config['avatar_min_height']) + { + if ($data['width'] < $config['avatar_min_width'] || $data['height'] < $config['avatar_min_height']) + { + $error[] = sprintf($user->lang['AVATAR_WRONG_SIZE'], $config['avatar_min_width'], $config['avatar_min_height'], $config['avatar_max_width'], $config['avatar_max_height'], $data['width'], $data['height']); + } + } + } + + if (!sizeof($error)) + { + $submit_ary['avatar_width'] = $data['width']; + $submit_ary['avatar_height'] = $data['height']; + } + } + + if ((isset($submit_ary['avatar']) && $submit_ary['avatar'] && (!isset($group_row['group_avatar']))) || $delete) + { + if (isset($group_row['group_avatar']) && $group_row['group_avatar']) + { + avatar_delete('group', $group_row, true); + } + } + + if (!check_form_key('ucp_groups')) + { + $error[] = $user->lang['FORM_INVALID']; + } + + if (!sizeof($error)) + { + // Only set the rank, colour, etc. if it's changed or if we're adding a new + // group. This prevents existing group members being updated if no changes + // were made. + + $group_attributes = array(); + $test_variables = array('rank', 'colour', 'avatar', 'avatar_type', 'avatar_width', 'avatar_height', 'receive_pm', 'legend', 'message_limit', 'max_recipients'); + foreach ($test_variables as $test) + { + if ($action == 'add' || (isset($submit_ary[$test]) && $group_row['group_' . $test] != $submit_ary[$test])) + { + $group_attributes['group_' . $test] = $group_row['group_' . $test] = $submit_ary[$test]; + } + } + + if (!($error = group_create($group_id, $group_type, $group_name, $group_desc, $group_attributes, $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies))) + { + $cache->destroy('sql', GROUPS_TABLE); + + $message = ($action == 'edit') ? 'GROUP_UPDATED' : 'GROUP_CREATED'; + trigger_error($user->lang[$message] . $return_page); + } + } + + if (sizeof($error)) + { + $group_rank = $submit_ary['rank']; + + $group_desc_data = array( + 'text' => $group_desc, + 'allow_bbcode' => $allow_desc_bbcode, + 'allow_smilies' => $allow_desc_smilies, + 'allow_urls' => $allow_desc_urls + ); + } + } + else if (!$group_id) + { + $group_name = utf8_normalize_nfc(request_var('group_name', '', true)); + $group_desc_data = array( + 'text' => '', + 'allow_bbcode' => true, + 'allow_smilies' => true, + 'allow_urls' => true + ); + $group_rank = 0; + $group_type = GROUP_OPEN; + } + else + { + $group_desc_data = generate_text_for_edit($group_row['group_desc'], $group_row['group_desc_uid'], $group_row['group_desc_options']); + $group_rank = $group_row['group_rank']; + } + + $sql = 'SELECT * + FROM ' . RANKS_TABLE . ' + WHERE rank_special = 1 + ORDER BY rank_title'; + $result = $db->sql_query($sql); + + $rank_options = '<option value="0"' . ((!$group_rank) ? ' selected="selected"' : '') . '>' . $user->lang['USER_DEFAULT'] . '</option>'; + while ($row = $db->sql_fetchrow($result)) + { + $selected = ($group_rank && $row['rank_id'] == $group_rank) ? ' selected="selected"' : ''; + $rank_options .= '<option value="' . $row['rank_id'] . '"' . $selected . '>' . $row['rank_title'] . '</option>'; + } + $db->sql_freeresult($result); + + $type_free = ($group_type == GROUP_FREE) ? ' checked="checked"' : ''; + $type_open = ($group_type == GROUP_OPEN) ? ' checked="checked"' : ''; + $type_closed = ($group_type == GROUP_CLOSED) ? ' checked="checked"' : ''; + $type_hidden = ($group_type == GROUP_HIDDEN) ? ' checked="checked"' : ''; + + $display_gallery = request::is_set_post('display_gallery'); + + if ($config['allow_avatar_local'] && $display_gallery) + { + avatar_gallery($category, $avatar_select, 4); + } + + $avatars_enabled = ($can_upload || ($config['allow_avatar_local'] || $config['allow_avatar_remote'])) ? true : false; + + $template->assign_vars(array( + 'S_EDIT' => true, + 'S_INCLUDE_SWATCH' => true, + 'S_CAN_UPLOAD' => $can_upload, + 'S_FORM_ENCTYPE' => ($can_upload) ? ' enctype="multipart/form-data"' : '', + 'S_ERROR' => (sizeof($error)) ? true : false, + 'S_SPECIAL_GROUP' => ($group_type == GROUP_SPECIAL) ? true : false, + 'S_AVATARS_ENABLED' => $avatars_enabled, + 'S_DISPLAY_GALLERY' => ($config['allow_avatar_local'] && !$display_gallery) ? true : false, + 'S_IN_GALLERY' => ($config['allow_avatar_local'] && $display_gallery) ? true : false, + + 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '', + 'GROUP_RECEIVE_PM' => (isset($group_row['group_receive_pm']) && $group_row['group_receive_pm']) ? ' checked="checked"' : '', + 'GROUP_MESSAGE_LIMIT' => (isset($group_row['group_message_limit'])) ? $group_row['group_message_limit'] : 0, + 'GROUP_MAX_RECIPIENTS' => (isset($group_row['group_max_recipients'])) ? $group_row['group_max_recipients'] : 0, + + 'GROUP_DESC' => $group_desc_data['text'], + 'S_DESC_BBCODE_CHECKED' => $group_desc_data['allow_bbcode'], + 'S_DESC_URLS_CHECKED' => $group_desc_data['allow_urls'], + 'S_DESC_SMILIES_CHECKED'=> $group_desc_data['allow_smilies'], + + 'S_RANK_OPTIONS' => $rank_options, + 'AVATAR_MAX_FILESIZE' => $config['avatar_filesize'], + + 'GROUP_TYPE_FREE' => GROUP_FREE, + 'GROUP_TYPE_OPEN' => GROUP_OPEN, + 'GROUP_TYPE_CLOSED' => GROUP_CLOSED, + 'GROUP_TYPE_HIDDEN' => GROUP_HIDDEN, + 'GROUP_TYPE_SPECIAL' => GROUP_SPECIAL, + + 'GROUP_FREE' => $type_free, + 'GROUP_OPEN' => $type_open, + 'GROUP_CLOSED' => $type_closed, + 'GROUP_HIDDEN' => $type_hidden, + + 'U_SWATCH' => append_sid(CONFIG_ADM_FOLDER . '/swatch', 'form=ucp&name=group_colour'), + 'S_UCP_ACTION' => $this->u_action . "&action=$action&g=$group_id", + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + )); + + break; + + case 'list': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $user->add_lang(array('acp/groups', 'acp/common')); + $start = request_var('start', 0); + + // Grab the leaders - always, on every page... + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 1 + ORDER BY ug.user_pending DESC, u.username_clean"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'U_USER_VIEW' => get_username_string('profile', $row['user_id'], $row['username']), + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + // Total number of group members (non-leaders) + $sql = 'SELECT COUNT(user_id) AS total_members + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + AND group_leader = 0"; + $result = $db->sql_query($sql); + $total_members = (int) $db->sql_fetchfield('total_members'); + $db->sql_freeresult($result); + + // Grab the members + $sql = 'SELECT u.user_id, u.username, u.username_clean, u.user_colour, u.user_regdate, u.user_posts, u.group_id, ug.group_leader, ug.user_pending + FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . " ug + WHERE ug.group_id = $group_id + AND u.user_id = ug.user_id + AND ug.group_leader = 0 + ORDER BY ug.user_pending DESC, u.username_clean"; + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $pending = false; + $approved = false; + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_pending'] && !$pending) + { + $template->assign_block_vars('member', array( + 'S_PENDING' => true) + ); + $template->assign_var('S_PENDING_SET', true); + + $pending = true; + } + else if (!$row['user_pending'] && !$approved) + { + $template->assign_block_vars('member', array( + 'S_APPROVED' => true) + ); + $template->assign_var('S_APPROVED_SET', true); + + $approved = true; + } + + $template->assign_block_vars('member', array( + 'USERNAME' => $row['username'], + 'USERNAME_COLOUR' => $row['user_colour'], + 'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']), + 'U_USER_VIEW' => get_username_string('profile', $row['user_id'], $row['username']), + 'S_GROUP_DEFAULT' => ($row['group_id'] == $group_id) ? true : false, + 'JOINED' => ($row['user_regdate']) ? $user->format_date($row['user_regdate']) : ' - ', + 'USER_POSTS' => $row['user_posts'], + 'USER_ID' => $row['user_id']) + ); + } + $db->sql_freeresult($result); + + $s_action_options = ''; + $options = array('default' => 'DEFAULT', 'approve' => 'APPROVE', 'deleteusers' => 'DELETE'); + + foreach ($options as $option => $lang) + { + $s_action_options .= '<option value="' . $option . '">' . $user->lang['GROUP_' . $lang] . '</option>'; + } + + $template->assign_vars(array( + 'S_LIST' => true, + 'S_ACTION_OPTIONS' => $s_action_options, + 'S_ON_PAGE' => on_page($total_members, $config['topics_per_page'], $start), + 'PAGINATION' => generate_pagination($this->u_action . "&action=$action&g=$group_id", $total_members, $config['topics_per_page'], $start), + + 'U_ACTION' => $this->u_action . "&g=$group_id", + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=ucp&field=usernames'), + )); + + break; + + case 'approve': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $user->add_lang('acp/groups'); + + // Approve, demote or promote + group_user_attributes('approve', $group_id, $mark_ary, false, false); + + trigger_error($user->lang['USERS_APPROVED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + + break; + + case 'default': + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (confirm_box(true)) + { + if (!sizeof($mark_ary)) + { + $start = 0; + + do + { + $sql = 'SELECT user_id + FROM ' . USER_GROUP_TABLE . " + WHERE group_id = $group_id + ORDER BY user_id"; + $result = $db->sql_query_limit($sql, 200, $start); + + $mark_ary = array(); + if ($row = $db->sql_fetchrow($result)) + { + do + { + $mark_ary[] = $row['user_id']; + } + while ($row = $db->sql_fetchrow($result)); + + group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); + + $start = (sizeof($mark_ary) < 200) ? 0 : $start + 200; + } + else + { + $start = 0; + } + $db->sql_freeresult($result); + } + while ($start); + } + else + { + group_user_attributes('default', $group_id, $mark_ary, false, $group_row['group_name'], $group_row); + } + + $user->add_lang('acp/groups'); + + trigger_error($user->lang['GROUP_DEFS_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + $user->add_lang('acp/common'); + + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + break; + + case 'deleteusers': + + $user->add_lang(array('acp/groups', 'acp/common')); + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $group_row['group_name'] = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + if (confirm_box(true)) + { + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + $error = group_user_del($group_id, $mark_ary, false, $group_row['group_name']); + + if ($error) + { + trigger_error($user->lang[$error] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + + trigger_error($user->lang['GROUP_USERS_REMOVE'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mark' => $mark_ary, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action)) + ); + } + + break; + + case 'addusers': + + $user->add_lang(array('acp/groups', 'acp/common')); + + $names = utf8_normalize_nfc(request_var('usernames', '', true)); + + if (!$group_id) + { + trigger_error($user->lang['NO_GROUP'] . $return_page); + } + + if (!$names) + { + trigger_error($user->lang['NO_USERS'] . $return_page); + } + + if (!($row = group_memberships($group_id, $user->data['user_id']))) + { + trigger_error($user->lang['NOT_MEMBER_OF_GROUP'] . $return_page); + } + list(, $row) = each($row); + + if (!$row['group_leader']) + { + trigger_error($user->lang['NOT_LEADER_OF_GROUP'] . $return_page); + } + + $name_ary = array_unique(explode("\n", $names)); + $group_name = ($group_row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $group_row['group_name']] : $group_row['group_name']; + + $default = request_var('default', 0); + + if (confirm_box(true)) + { + // Add user/s to group + if ($error = group_user_add($group_id, false, $name_ary, $group_name, $default, 0, 0, $group_row)) + { + trigger_error($user->lang[$error] . $return_page); + } + + trigger_error($user->lang['GROUP_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + } + else + { + $s_hidden_fields = array( + 'default' => $default, + 'usernames' => $names, + 'g' => $group_id, + 'i' => $id, + 'mode' => $mode, + 'action' => $action + ); + confirm_box(false, sprintf($user->lang['GROUP_CONFIRM_ADD_USER' . ((sizeof($name_ary) == 1) ? '' : 'S')], implode(', ', $name_ary)), build_hidden_fields($s_hidden_fields)); + } + + trigger_error($user->lang['NO_USERS_ADDED'] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '&action=list&g=' . $group_id . '">', '</a>')); + + break; + + default: + $user->add_lang('acp/common'); + + $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_desc, g.group_desc_uid, g.group_desc_bitfield, g.group_desc_options, g.group_type, ug.group_leader + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND g.group_id = ug.group_id + AND ug.group_leader = 1 + ORDER BY g.group_type DESC, g.group_name'; + $result = $db->sql_query($sql); + + while ($value = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('leader', array( + 'GROUP_NAME' => ($value['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $value['group_name']] : $value['group_name'], + 'GROUP_DESC' => generate_text_for_display($value['group_desc'], $value['group_desc_uid'], $value['group_desc_bitfield'], $value['group_desc_options']), + 'GROUP_TYPE' => $value['group_type'], + 'GROUP_ID' => $value['group_id'], + 'GROUP_COLOUR' => $value['group_colour'], + + 'U_LIST' => $this->u_action . "&action=list&g={$value['group_id']}", + 'U_EDIT' => $this->u_action . "&action=edit&g={$value['group_id']}") + ); + } + $db->sql_freeresult($result); + + break; + } + + break; + } + + $this->tpl_name = 'ucp_groups_' . $mode; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_main.php b/phpBB/modules/ucp/ucp_main.php new file mode 100644 index 0000000000..ca573ca044 --- /dev/null +++ b/phpBB/modules/ucp/ucp_main.php @@ -0,0 +1,830 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_main +* UCP Front Panel +* @package ucp +*/ +class ucp_main +{ + var $p_master; + var $u_action; + + function __construct(&$p_master) + { + $this->p_master = &$p_master; + } + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + switch ($mode) + { + case 'front': + + $user->add_lang('memberlist'); + + $sql_from = TOPICS_TABLE . ' t '; + $sql_select = ''; + + if ($config['load_db_track']) + { + $sql_from .= ' LEFT JOIN ' . TOPICS_POSTED_TABLE . ' tp ON (tp.topic_id = t.topic_id + AND tp.user_id = ' . $user->data['user_id'] . ')'; + $sql_select .= ', tp.topic_posted'; + } + + if ($config['load_db_lastread']) + { + $sql_from .= ' LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id + AND tt.user_id = ' . $user->data['user_id'] . ')'; + $sql_select .= ', tt.mark_time'; + } + + $topic_type = $user->lang['VIEW_TOPIC_GLOBAL']; + $folder = 'global_read'; + $folder_new = 'global_unread'; + + // Get cleaned up list... return only those forums not having the f_read permission + $forum_ary = $auth->acl_getf('!f_read', true); + $forum_ary = array_unique(array_keys($forum_ary)); + + // Determine first forum the user is able to read into - for global announcement link + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE . ' + WHERE forum_type = ' . FORUM_POST; + + if (sizeof($forum_ary)) + { + $sql .= ' AND ' . $db->sql_in_set('forum_id', $forum_ary, true); + } + $result = $db->sql_query_limit($sql, 1); + $g_forum_id = (int) $db->sql_fetchfield('forum_id'); + $db->sql_freeresult($result); + + $sql = "SELECT t.* $sql_select + FROM $sql_from + WHERE t.forum_id = 0 + AND t.topic_type = " . POST_GLOBAL . ' + ORDER BY t.topic_last_post_time DESC'; + + $topic_list = $rowset = array(); + // If the user can't see any forums, he can't read any posts because fid of 0 is invalid + if ($g_forum_id) + { + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_list[] = $row['topic_id']; + $rowset[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + + $topic_tracking_info = array(); + if ($config['load_db_lastread']) + { + $topic_tracking_info = get_topic_tracking(0, $topic_list, $rowset, false, $topic_list); + } + else + { + $topic_tracking_info = get_complete_topic_tracking(0, $topic_list, $topic_list); + } + + foreach ($topic_list as $topic_id) + { + $row = &$rowset[$topic_id]; + + $forum_id = $row['forum_id']; + $topic_id = $row['topic_id']; + + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + $folder_img = ($unread_topic) ? $folder_new : $folder; + $folder_alt = ($unread_topic) ? 'NEW_POSTS' : (($row['topic_status'] == ITEM_LOCKED) ? 'TOPIC_LOCKED' : 'NO_NEW_POSTS'); + + if ($row['topic_status'] == ITEM_LOCKED) + { + $folder_img .= '_locked'; + } + + // Posted image? + if (!empty($row['topic_posted']) && $row['topic_posted']) + { + $folder_img .= '_mine'; + } + + $template->assign_block_vars('topicrow', array( + 'FORUM_ID' => $forum_id, + 'TOPIC_ID' => $topic_id, + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => censor_text($row['topic_last_post_subject']), + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'TOPIC_TITLE' => censor_text($row['topic_title']), + 'TOPIC_TYPE' => $topic_type, + + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, 'src'), + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', '') : '', + + 'S_USER_POSTED' => (!empty($row['topic_posted']) && $row['topic_posted']) ? true : false, + 'S_UNREAD' => $unread_topic, + + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_LAST_POST' => append_sid('viewtopic', "f=$g_forum_id&t=$topic_id&p=" . $row['topic_last_post_id']) . '#p' . $row['topic_last_post_id'], + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_NEWEST_POST' => append_sid('viewtopic', "f=$g_forum_id&t=$topic_id&view=unread") . '#unread', + 'U_VIEW_TOPIC' => append_sid('viewtopic', "f=$g_forum_id&t=$topic_id")) + ); + } + + if ($config['load_user_activity']) + { + if (!function_exists('display_user_activity')) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + } + display_user_activity($user->data); + } + + // Do the relevant calculations + $memberdays = max(1, round((time() - $user->data['user_regdate']) / 86400)); + $posts_per_day = $user->data['user_posts'] / $memberdays; + $percentage = ($config['num_posts']) ? min(100, ($user->data['user_posts'] / $config['num_posts']) * 100) : 0; + + $template->assign_vars(array( + 'USER_COLOR' => (!empty($user->data['user_colour'])) ? $user->data['user_colour'] : '', + 'JOINED' => $user->format_date($user->data['user_regdate']), + 'VISITED' => (empty($last_visit)) ? ' - ' : $user->format_date($last_visit), + 'WARNINGS' => ($user->data['user_warnings']) ? $user->data['user_warnings'] : 0, + 'POSTS' => ($user->data['user_posts']) ? $user->data['user_posts'] : 0, + 'POSTS_DAY' => sprintf($user->lang['POST_DAY'], $posts_per_day), + 'POSTS_PCT' => sprintf($user->lang['POST_PCT'], $percentage), + + 'OCCUPATION' => (!empty($row['user_occ'])) ? $row['user_occ'] : '', + 'INTERESTS' => (!empty($row['user_interests'])) ? $row['user_interests'] : '', + +// 'S_GROUP_OPTIONS' => $group_options, + + 'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid('search', 'author_id=' . $user->data['user_id'] . '&sr=posts') : '', + )); + + break; + + case 'subscribed': + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $user->add_lang('viewforum'); + + add_form_key('ucp_front_subscribed'); + + $unwatch = request::is_set_post('unwatch'); + + if ($unwatch) + { + if (check_form_key('ucp_front_subscribed')) + { + $forums = array_keys(request_var('f', array(0 => 0))); + $topics = array_keys(request_var('t', array(0 => 0))); + $msg = ''; + + if (sizeof($forums) || sizeof($topics)) + { + $l_unwatch = ''; + if (sizeof($forums)) + { + $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . ' + WHERE ' . $db->sql_in_set('forum_id', $forums) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $l_unwatch .= '_FORUMS'; + } + + if (sizeof($topics)) + { + $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', $topics) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $l_unwatch .= '_TOPICS'; + } + $msg = $user->lang['UNWATCHED' . $l_unwatch]; + } + else + { + $msg = $user->lang['NO_WATCHED_SELECTED']; + } + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . append_sid('ucp', "i=$id&mode=subscribed") . '">', '</a>'); + meta_refresh(3, append_sid('ucp', "i=$id&mode=subscribed")); + trigger_error($message); + } + + $forbidden_forums = array(); + + if ($config['allow_forum_notify']) + { + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + + $sql_array = array( + 'SELECT' => 'f.*', + + 'FROM' => array( + FORUMS_WATCH_TABLE => 'fw', + FORUMS_TABLE => 'f' + ), + + 'WHERE' => 'fw.user_id = ' . $user->data['user_id'] . ' + AND f.forum_id = fw.forum_id + AND ' . $db->sql_in_set('f.forum_id', $forbidden_forums, true, true), + + 'ORDER_BY' => 'left_id' + ); + + if ($config['load_db_lastread']) + { + $sql_array['LEFT_JOIN'] = array( + array( + 'FROM' => array(FORUMS_TRACK_TABLE => 'ft'), + 'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND ft.forum_id = f.forum_id' + ) + ); + + $sql_array['SELECT'] .= ', ft.mark_time '; + } + else + { + $tracking_topics = request::variable($config['cookie_name'] . '_track', '', false, request::COOKIE); + $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $forum_id = $row['forum_id']; + + if ($config['load_db_lastread']) + { + $forum_check = (!empty($row['mark_time'])) ? $row['mark_time'] : $user->data['user_lastmark']; + } + else + { + $forum_check = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + $config['board_startdate']) : $user->data['user_lastmark']; + } + + $unread_forum = ($row['forum_last_post_time'] > $forum_check) ? true : false; + + // Which folder should we display? + if ($row['forum_status'] == ITEM_LOCKED) + { + $folder_image = ($unread_forum) ? 'forum_unread_locked' : 'forum_read_locked'; + $folder_alt = 'FORUM_LOCKED'; + } + else + { + $folder_image = ($unread_forum) ? 'forum_unread' : 'forum_read'; + $folder_alt = ($unread_forum) ? 'NEW_POSTS' : 'NO_NEW_POSTS'; + } + + // Create last post link information, if appropriate + if ($row['forum_last_post_id']) + { + $last_post_time = $user->format_date($row['forum_last_post_time']); + $last_post_url = append_sid('viewtopic', "f=$forum_id&p=" . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id']; + } + else + { + $last_post_time = $last_post_url = ''; + } + + $template->assign_block_vars('forumrow', array( + 'FORUM_ID' => $forum_id, + 'FORUM_FOLDER_IMG' => $user->img($folder_image, $folder_alt), + 'FORUM_FOLDER_IMG_SRC' => $user->img($folder_image, $folder_alt, 'src'), + 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . PHPBB_ROOT_PATH . $row['forum_image'] . '" alt="' . $user->lang[$folder_alt] . '" />' : '', + 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? PHPBB_ROOT_PATH . $row['forum_image'] : '', + 'FORUM_NAME' => $row['forum_name'], + 'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), + 'LAST_POST_SUBJECT' => $row['forum_last_post_subject'], + 'LAST_POST_TIME' => $last_post_time, + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), + + 'U_LAST_POST' => $last_post_url, + 'U_VIEWFORUM' => append_sid('viewforum', 'f=' . $row['forum_id'])) + ); + } + $db->sql_freeresult($result); + } + + // Subscribed Topics + if ($config['allow_topic_notify']) + { + if (empty($forbidden_forums)) + { + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + } + $this->assign_topiclist('subscribed', $forbidden_forums); + } + + $template->assign_vars(array( + 'S_TOPIC_NOTIFY' => $config['allow_topic_notify'], + 'S_FORUM_NOTIFY' => $config['allow_forum_notify'], + )); + + break; + + case 'bookmarks': + + if (!$config['allow_bookmarks']) + { + $template->assign_vars(array( + 'S_NO_DISPLAY_BOOKMARKS' => true) + ); + break; + } + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $user->add_lang('viewforum'); + + if (request::is_set_post('unbookmark')) + { + $s_hidden_fields = array('unbookmark' => 1); + $topics = array_keys(request::variable('t', array(0 => 0), false, request::POST)); + $url = $this->u_action; + + if (!sizeof($topics)) + { + trigger_error('NO_BOOKMARKS_SELECTED'); + } + + foreach ($topics as $topic_id) + { + $s_hidden_fields['t'][$topic_id] = 1; + } + + if (confirm_box(true)) + { + $sql = 'DELETE FROM ' . BOOKMARKS_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('topic_id', $topics); + $db->sql_query($sql); + + meta_refresh(3, $url); + $message = $user->lang['BOOKMARKS_REMOVED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $url . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'REMOVE_SELECTED_BOOKMARKS', build_hidden_fields($s_hidden_fields)); + } + } + $forbidden_forums = $auth->acl_getf('!f_read', true); + $forbidden_forums = array_unique(array_keys($forbidden_forums)); + + $this->assign_topiclist('bookmarks', $forbidden_forums); + + break; + + case 'drafts': + + $pm_drafts = ($this->p_master->p_name == 'pm') ? true : false; + $template->assign_var('S_SHOW_DRAFTS', true); + + $user->add_lang('posting'); + + $edit = request::is_set('edit'); + $draft_id = request::variable('edit', 0); + $submit = request::is_set_post('submit'); + $delete = request::is_set_post('delete'); + + $s_hidden_fields = ($edit) ? '<input type="hidden" name="edit" value="' . $draft_id . '" />' : ''; + $draft_subject = $draft_message = ''; + add_form_key('ucp_draft'); + + if ($delete) + { + if (check_form_key('ucp_draft')) + { + $drafts = array_keys(request_var('d', array(0 => 0))); + + if (sizeof($drafts)) + { + $sql = 'DELETE FROM ' . DRAFTS_TABLE . ' + WHERE ' . $db->sql_in_set('draft_id', $drafts) . ' + AND user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + $msg = $user->lang['DRAFTS_DELETED']; + unset($drafts); + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + meta_refresh(3, $this->u_action); + trigger_error($message); + } + + if ($submit && $edit) + { + $draft_subject = utf8_normalize_nfc(request_var('subject', '', true)); + $draft_message = utf8_normalize_nfc(request_var('message', '', true)); + if (check_form_key('ucp_draft')) + { + if ($draft_message && $draft_subject) + { + $draft_row = array( + 'draft_subject' => $draft_subject, + 'draft_message' => $draft_message + ); + + $sql = 'UPDATE ' . DRAFTS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $draft_row) . " + WHERE draft_id = $draft_id + AND user_id = " . $user->data['user_id']; + $db->sql_query($sql); + + $message = $user->lang['DRAFT_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + + meta_refresh(3, $this->u_action); + trigger_error($message); + } + else + { + $template->assign_var('ERROR', ($draft_message == '') ? $user->lang['EMPTY_DRAFT'] : (($draft_subject == '') ? $user->lang['EMPTY_DRAFT_TITLE'] : '')); + } + } + else + { + $template->assign_var('ERROR', $user->lang['FORM_INVALID']); + } + } + + if (!$pm_drafts) + { + $sql = 'SELECT d.*, f.forum_name + FROM ' . DRAFTS_TABLE . ' d, ' . FORUMS_TABLE . ' f + WHERE d.user_id = ' . $user->data['user_id'] . ' ' . + (($edit) ? "AND d.draft_id = $draft_id" : '') . ' + AND f.forum_id = d.forum_id + ORDER BY d.save_time DESC'; + } + else + { + $sql = 'SELECT * FROM ' . DRAFTS_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' ' . + (($edit) ? "AND draft_id = $draft_id" : '') . ' + AND forum_id = 0 + AND topic_id = 0 + ORDER BY save_time DESC'; + } + $result = $db->sql_query($sql); + + $draftrows = $topic_ids = array(); + + while ($row = $db->sql_fetchrow($result)) + { + if ($row['topic_id']) + { + $topic_ids[] = (int) $row['topic_id']; + } + $draftrows[] = $row; + } + $db->sql_freeresult($result); + + if (sizeof($topic_ids)) + { + $sql = 'SELECT topic_id, forum_id, topic_title + FROM ' . TOPICS_TABLE . ' + WHERE ' . $db->sql_in_set('topic_id', array_unique($topic_ids)); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $topic_rows[$row['topic_id']] = $row; + } + $db->sql_freeresult($result); + } + unset($topic_ids); + + $template->assign_var('S_EDIT_DRAFT', $edit); + + $row_count = 0; + foreach ($draftrows as $draft) + { + $link_topic = $link_forum = $link_pm = false; + $insert_url = $view_url = $title = ''; + + if (isset($topic_rows[$draft['topic_id']]) && $auth->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) + { + $link_topic = true; + $view_url = append_sid('viewtopic', 'f=' . $topic_rows[$draft['topic_id']]['forum_id'] . '&t=' . $draft['topic_id']); + $title = $topic_rows[$draft['topic_id']]['topic_title']; + + $insert_url = append_sid('posting', 'f=' . $topic_rows[$draft['topic_id']]['forum_id'] . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); + } + else if ($auth->acl_get('f_read', $draft['forum_id'])) + { + $link_forum = true; + $view_url = append_sid('viewforum', 'f=' . $draft['forum_id']); + $title = $draft['forum_name']; + + $insert_url = append_sid('posting', 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); + } + else if ($pm_drafts) + { + $link_pm = true; + $insert_url = append_sid('ucp', "i=$id&mode=compose&d=" . $draft['draft_id']); + } + + $template_row = array( + 'DATE' => $user->format_date($draft['save_time']), + 'DRAFT_MESSAGE' => ($submit) ? $draft_message : $draft['draft_message'], + 'DRAFT_SUBJECT' => ($submit) ? $draft_subject : $draft['draft_subject'], + 'TITLE' => $title, + + 'DRAFT_ID' => $draft['draft_id'], + 'FORUM_ID' => $draft['forum_id'], + 'TOPIC_ID' => $draft['topic_id'], + + 'U_VIEW' => $view_url, + 'U_VIEW_EDIT' => $this->u_action . '&edit=' . $draft['draft_id'], + 'U_INSERT' => $insert_url, + + 'S_LINK_TOPIC' => $link_topic, + 'S_LINK_FORUM' => $link_forum, + 'S_LINK_PM' => $link_pm, + 'S_HIDDEN_FIELDS' => $s_hidden_fields + ); + $row_count++; + + ($edit) ? $template->assign_vars($template_row) : $template->assign_block_vars('draftrow', $template_row); + } + + if (!$edit) + { + $template->assign_var('S_DRAFT_ROWS', $row_count); + } + + break; + } + + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_MAIN_' . strtoupper($mode)], + + 'S_DISPLAY_MARK_ALL' => ($mode == 'watched' || ($mode == 'drafts' && !request::is_set('edit', request::GET))) ? true : false, + 'S_HIDDEN_FIELDS' => (isset($s_hidden_fields)) ? $s_hidden_fields : '', + 'S_UCP_ACTION' => $this->u_action, + + 'LAST_POST_IMG' => $user->img('icon_topic_latest', 'VIEW_LATEST_POST'), + 'NEWEST_POST_IMG' => $user->img('icon_topic_newest', 'VIEW_NEWEST_POST'), + )); + + // Set desired template + $this->tpl_name = 'ucp_main_' . $mode; + $this->page_title = 'UCP_MAIN_' . strtoupper($mode); + } + + /** + * Build and assign topiclist for bookmarks/subscribed topics + */ + function assign_topiclist($mode = 'subscribed', $forbidden_forum_ary = array()) + { + global $user, $db, $template, $config, $auth; + + $table = ($mode == 'subscribed') ? TOPICS_WATCH_TABLE : BOOKMARKS_TABLE; + $start = request_var('start', 0); + + $sql_array = array( + 'SELECT' => 'COUNT(t.topic_id) as topics_count', + + 'FROM' => array( + $table => 'i', + TOPICS_TABLE => 't' + ), + + 'WHERE' => 'i.topic_id = t.topic_id + AND i.user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), + ); + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query($sql); + $topics_count = (int) $db->sql_fetchfield('topics_count'); + $db->sql_freeresult($result); + + if ($topics_count) + { + $template->assign_vars(array( + 'PAGINATION' => generate_pagination($this->u_action, $topics_count, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($topics_count, $config['topics_per_page'], $start), + 'TOTAL_TOPICS' => ($topics_count == 1) ? $user->lang['VIEW_FORUM_TOPIC'] : sprintf($user->lang['VIEW_FORUM_TOPICS'], $topics_count)) + ); + } + + if ($mode == 'subscribed') + { + $sql_array = array( + 'SELECT' => 't.*, f.forum_name', + + 'FROM' => array( + TOPICS_WATCH_TABLE => 'tw', + TOPICS_TABLE => 't' + ), + + 'WHERE' => 'tw.user_id = ' . $user->data['user_id'] . ' + AND t.topic_id = tw.topic_id + AND ' . $db->sql_in_set('t.forum_id', $forbidden_forum_ary, true, true), + + + 'ORDER_BY' => 't.topic_last_post_time DESC' + ); + + $sql_array['LEFT_JOIN'] = array(); + } + else + { + $sql_array = array( + 'SELECT' => 't.*, f.forum_name, b.topic_id as b_topic_id', + + 'FROM' => array( + BOOKMARKS_TABLE => 'b', + ), + + 'WHERE' => 'b.user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('f.forum_id', $forbidden_forum_ary, true, true), + + 'ORDER_BY' => 't.topic_last_post_time DESC' + ); + + $sql_array['LEFT_JOIN'] = array(); + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TABLE => 't'), 'ON' => 'b.topic_id = t.topic_id'); + } + + $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TABLE => 'f'), 'ON' => 't.forum_id = f.forum_id'); + + if ($config['load_db_lastread']) + { + $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.forum_id = t.forum_id AND ft.user_id = ' . $user->data['user_id']); + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_TRACK_TABLE => 'tt'), 'ON' => 'tt.topic_id = t.topic_id AND tt.user_id = ' . $user->data['user_id']); + $sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time AS forum_mark_time'; + } + + if ($config['load_db_track']) + { + $sql_array['LEFT_JOIN'][] = array('FROM' => array(TOPICS_POSTED_TABLE => 'tp'), 'ON' => 'tp.topic_id = t.topic_id AND tp.user_id = ' . $user->data['user_id']); + $sql_array['SELECT'] .= ', tp.topic_posted'; + } + + $sql = $db->sql_build_query('SELECT', $sql_array); + $result = $db->sql_query_limit($sql, $config['topics_per_page'], $start); + + $topic_list = $topic_forum_list = $global_announce_list = $rowset = array(); + while ($row = $db->sql_fetchrow($result)) + { + $topic_id = (isset($row['b_topic_id'])) ? $row['b_topic_id'] : $row['topic_id']; + + $topic_list[] = $topic_id; + $rowset[$topic_id] = $row; + + $topic_forum_list[$row['forum_id']]['forum_mark_time'] = ($config['load_db_lastread']) ? $row['forum_mark_time'] : 0; + $topic_forum_list[$row['forum_id']]['topics'][] = $topic_id; + + if ($row['topic_type'] == POST_GLOBAL) + { + $global_announce_list[] = $topic_id; + } + } + $db->sql_freeresult($result); + + $topic_tracking_info = array(); + if ($config['load_db_lastread']) + { + foreach ($topic_forum_list as $f_id => $topic_row) + { + $topic_tracking_info += get_topic_tracking($f_id, $topic_row['topics'], $rowset, array($f_id => $topic_row['forum_mark_time']), ($f_id == 0) ? $global_announce_list : false); + } + } + else + { + foreach ($topic_forum_list as $f_id => $topic_row) + { + $topic_tracking_info += get_complete_topic_tracking($f_id, $topic_row['topics'], $global_announce_list); + } + } + + foreach ($topic_list as $topic_id) + { + $row = &$rowset[$topic_id]; + + $forum_id = $row['forum_id']; + $topic_id = (isset($row['b_topic_id'])) ? $row['b_topic_id'] : $row['topic_id']; + + $unread_topic = (isset($topic_tracking_info[$topic_id]) && $row['topic_last_post_time'] > $topic_tracking_info[$topic_id]) ? true : false; + + // Replies + $replies = ($auth->acl_get('m_approve', $forum_id)) ? $row['topic_replies_real'] : $row['topic_replies']; + + if ($row['topic_status'] == ITEM_MOVED && !empty($row['topic_moved_id'])) + { + $topic_id = $row['topic_moved_id']; + } + + // Get folder img, topic status/type related information + $folder_img = $folder_alt = $topic_type = ''; + topic_status($row, $replies, $unread_topic, $folder_img, $folder_alt, $topic_type); + + $view_topic_url = append_sid('viewtopic', "f=$forum_id&t=$topic_id"); + + // Send vars to template + $template->assign_block_vars('topicrow', array( + 'FORUM_ID' => $forum_id, + 'TOPIC_ID' => $topic_id, + 'FIRST_POST_TIME' => $user->format_date($row['topic_time']), + 'LAST_POST_SUBJECT' => $row['topic_last_post_subject'], + 'LAST_POST_TIME' => $user->format_date($row['topic_last_post_time']), + 'LAST_VIEW_TIME' => $user->format_date($row['topic_last_view_time']), + + 'TOPIC_AUTHOR' => get_username_string('username', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'TOPIC_AUTHOR_FULL' => get_username_string('full', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + 'U_TOPIC_AUTHOR' => get_username_string('profile', $row['topic_poster'], $row['topic_first_poster_name'], $row['topic_first_poster_colour']), + + 'LAST_POST_AUTHOR' => get_username_string('username', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_COLOUR' => get_username_string('colour', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'LAST_POST_AUTHOR_FULL' => get_username_string('full', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + 'U_LAST_POST_AUTHOR' => get_username_string('profile', $row['topic_last_poster_id'], $row['topic_last_poster_name'], $row['topic_last_poster_colour']), + + 'S_DELETED_TOPIC' => (!$row['topic_id']) ? true : false, + 'S_GLOBAL_TOPIC' => (!$forum_id) ? true : false, + + 'PAGINATION' => topic_generate_pagination($replies, append_sid('viewtopic', 'f=' . (($row['forum_id']) ? $row['forum_id'] : $forum_id) . "&t=$topic_id")), + 'REPLIES' => $replies, + 'VIEWS' => $row['topic_views'], + 'TOPIC_TITLE' => censor_text($row['topic_title']), + 'TOPIC_TYPE' => $topic_type, + 'FORUM_NAME' => $row['forum_name'], + + 'TOPIC_FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'TOPIC_FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, 'src'), + 'TOPIC_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['img'] : '', + 'TOPIC_ICON_IMG_WIDTH' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['width'] : '', + 'TOPIC_ICON_IMG_HEIGHT' => (!empty($icons[$row['icon_id']])) ? $icons[$row['icon_id']]['height'] : '', + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_download') && $auth->acl_get('f_download', $forum_id) && $row['topic_attachment']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + + 'S_TOPIC_TYPE' => $row['topic_type'], + 'S_USER_POSTED' => (!empty($row['topic_posted'])) ? true : false, + 'S_UNREAD_TOPIC' => $unread_topic, + + 'U_NEWEST_POST' => append_sid('viewtopic', "f=$forum_id&t=$topic_id&view=unread") . '#unread', + 'U_LAST_POST' => $view_topic_url . '&p=' . $row['topic_last_post_id'] . '#p' . $row['topic_last_post_id'], + 'U_VIEW_TOPIC' => $view_topic_url, + 'U_VIEW_FORUM' => append_sid('viewforum', 'f=' . $forum_id), + )); + } + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_pm.php b/phpBB/modules/ucp/ucp_pm.php new file mode 100644 index 0000000000..b631357784 --- /dev/null +++ b/phpBB/modules/ucp/ucp_pm.php @@ -0,0 +1,409 @@ +<?php +/** +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Private Message Class +* +* _REQUEST['folder'] display folder with the id used +* _REQUEST['folder'] inbox|outbox|sentbox display folder with the associated name +* +* Display Messages (default to inbox) - mode=view +* Display single message - mode=view&p=[msg_id] or &p=[msg_id] (short linkage) +* +* if the folder id with (&f=[folder_id]) is used when displaying messages, one query will be saved. If it is not used, phpBB needs to grab +* the folder id first in order to display the input boxes and folder names and such things. ;) phpBB always checks this against the database to make +* sure the user is able to view the message. +* +* Composing Messages (mode=compose): +* To specific user (u=[user_id]) +* To specific group (g=[group_id]) +* Quoting a post (action=quotepost&p=[post_id]) +* Quoting a PM (action=quote&p=[msg_id]) +* Forwarding a PM (action=forward&p=[msg_id]) +* +* @package ucp +*/ +class ucp_pm +{ + var $u_action; + + function main($id, $mode) + { + global $user, $template, $auth, $db, $config; + + if (!$user->data['is_registered']) + { + trigger_error('NO_MESSAGE'); + } + + // Is PM disabled? + if (!$config['allow_privmsg']) + { + trigger_error('PM_DISABLED'); + } + + $user->add_lang('posting'); + $template->assign_var('S_PRIVMSGS', true); + + // Folder directly specified? + $folder_specified = request_var('folder', ''); + + if (!in_array($folder_specified, array('inbox', 'outbox', 'sentbox'))) + { + $folder_specified = (int) $folder_specified; + } + else + { + $folder_specified = ($folder_specified == 'inbox') ? PRIVMSGS_INBOX : (($folder_specified == 'outbox') ? PRIVMSGS_OUTBOX : PRIVMSGS_SENTBOX); + } + + if (!$folder_specified) + { + $mode = (!$mode) ? request_var('mode', 'view') : $mode; + } + else + { + $mode = 'view'; + } + + include(PHPBB_ROOT_PATH . 'includes/functions_privmsgs.' . PHP_EXT); + + switch ($mode) + { + // New private messages popup + case 'popup': + + $l_new_message = ''; + if ($user->data['is_registered']) + { + if ($user->data['user_new_privmsg']) + { + $l_new_message = ($user->data['user_new_privmsg'] == 1) ? $user->lang['YOU_NEW_PM'] : $user->lang['YOU_NEW_PMS']; + } + else + { + $l_new_message = $user->lang['YOU_NO_NEW_PM']; + } + } + + $template->assign_vars(array( + 'MESSAGE' => $l_new_message, + 'S_NOT_LOGGED_IN' => ($user->data['user_id'] == ANONYMOUS) ? true : false, + 'CLICK_TO_VIEW' => sprintf($user->lang['CLICK_VIEW_PRIVMSG'], '<a href="' . append_sid('ucp', 'i=pm&folder=inbox') . '" onclick="jump_to_inbox(this.href); return false;">', '</a>'), + 'U_INBOX' => append_sid('ucp', 'i=pm&folder=inbox'), + 'UA_INBOX' => append_sid('ucp', 'i=pm&folder=inbox', false)) + ); + + $tpl_file = 'ucp_pm_popup'; + break; + + // Compose message + case 'compose': + $action = request_var('action', 'post'); + + get_folder($user->data['user_id']); + + if (!$auth->acl_get('u_sendpm')) + { + trigger_error('NO_AUTH_SEND_MESSAGE'); + } + + include(PHPBB_ROOT_PATH . 'includes/ucp/ucp_pm_compose.' . PHP_EXT); + compose_pm($id, $mode, $action); + + $tpl_file = 'posting_body'; + break; + + case 'options': + set_user_message_limit(); + get_folder($user->data['user_id']); + + include(PHPBB_ROOT_PATH . 'includes/ucp/ucp_pm_options.' . PHP_EXT); + message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions); + + $tpl_file = 'ucp_pm_options'; + break; + + case 'drafts': + + get_folder($user->data['user_id']); + $this->p_name = 'pm'; + + // Call another module... please do not try this at home... Hoochie Coochie Man + include(PHPBB_ROOT_PATH . 'includes/ucp/ucp_main.' . PHP_EXT); + + $module = new ucp_main($this); + $module->u_action = $this->u_action; + $module->main($id, $mode); + + $this->tpl_name = $module->tpl_name; + $this->page_title = 'UCP_PM_DRAFTS'; + + unset($module); + return; + + break; + + case 'view': + + set_user_message_limit(); + + if ($folder_specified) + { + $folder_id = $folder_specified; + $action = 'view_folder'; + } + else + { + $folder_id = request_var('f', PRIVMSGS_NO_BOX); + $action = request_var('action', 'view_folder'); + } + + $msg_id = request_var('p', 0); + $view = request_var('view', ''); + + // View message if specified + if ($msg_id) + { + $action = 'view_message'; + } + + if (!$auth->acl_get('u_readpm')) + { + trigger_error('NO_AUTH_READ_MESSAGE'); + } + + // Do not allow hold messages to be seen + if ($folder_id == PRIVMSGS_HOLD_BOX) + { + trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); + } + + + // First Handle Mark actions and moving messages + $submit_mark = request::is_set_post('submit_mark'); + $move_pm = request::is_set_post('move_pm'); + $mark_option = request_var('mark_option', ''); + $dest_folder = request_var('dest_folder', PRIVMSGS_NO_BOX); + + // Is moving PM triggered through mark options? + if (!in_array($mark_option, array('mark_important', 'delete_marked')) && $submit_mark) + { + $move_pm = true; + $dest_folder = (int) $mark_option; + $submit_mark = false; + } + + // Move PM + if ($move_pm) + { + $move_msg_ids = request::variable('marked_msg_id', array(0), false, request::POST); + $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + + if (move_pm($user->data['user_id'], $user->data['message_limit'], $move_msg_ids, $dest_folder, $cur_folder_id)) + { + // Return to folder view if single message moved + if ($action == 'view_message') + { + $msg_id = 0; + $folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); + $action = 'view_folder'; + } + } + } + + // Message Mark Options + if ($submit_mark) + { + handle_mark_actions($user->data['user_id'], $mark_option); + } + + // If new messages arrived, place them into the appropriate folder + $num_not_moved = $num_removed = 0; + $release = request_var('release', 0); + + if ($user->data['user_new_privmsg'] && $action == 'view_folder') + { + $return = place_pm_into_folder($global_privmsgs_rules, $release); + $num_not_moved = $return['not_moved']; + $num_removed = $return['removed']; + } + + if (!$msg_id && $folder_id == PRIVMSGS_NO_BOX) + { + $folder_id = PRIVMSGS_INBOX; + } + else if ($msg_id && $folder_id == PRIVMSGS_NO_BOX) + { + $sql = 'SELECT folder_id + FROM ' . PRIVMSGS_TO_TABLE . " + WHERE msg_id = $msg_id + AND folder_id <> " . PRIVMSGS_NO_BOX . ' + AND user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_MESSAGE'); + } + $folder_id = (int) $row['folder_id']; + } + + $message_row = array(); + if ($action == 'view_message' && $msg_id) + { + // Get Message user want to see + if ($view == 'next' || $view == 'previous') + { + $sql_condition = ($view == 'next') ? '>' : '<'; + $sql_ordering = ($view == 'next') ? 'ASC' : 'DESC'; + + $sql = 'SELECT t.msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TABLE . " p2 + WHERE p2.msg_id = $msg_id + AND t.folder_id = $folder_id + AND t.user_id = " . $user->data['user_id'] . " + AND t.msg_id = p.msg_id + AND p.message_time $sql_condition p2.message_time + ORDER BY p.message_time $sql_ordering"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + $message = ($view == 'next') ? 'NO_NEWER_PM' : 'NO_OLDER_PM'; + trigger_error($message); + } + else + { + $msg_id = $row['msg_id']; + } + } + + $sql = 'SELECT t.*, p.*, u.* + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.folder_id = $folder_id + AND t.msg_id = p.msg_id + AND p.msg_id = $msg_id"; + $result = $db->sql_query($sql); + $message_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$message_row) + { + trigger_error('NO_MESSAGE'); + } + + // Update unread status + update_unread_status($message_row['pm_unread'], $message_row['msg_id'], $user->data['user_id'], $folder_id); + } + + $folder = get_folder($user->data['user_id'], $folder_id); + + $s_folder_options = $s_to_folder_options = ''; + foreach ($folder as $f_id => $folder_ary) + { + $option = '<option' . ((!in_array($f_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX))) ? ' class="sep"' : '') . ' value="' . $f_id . '"' . (($f_id == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . (($folder_ary['unread_messages']) ? ' [' . $folder_ary['unread_messages'] . '] ' : '') . '</option>'; + + $s_to_folder_options .= ($f_id != PRIVMSGS_OUTBOX && $f_id != PRIVMSGS_SENTBOX) ? $option : ''; + $s_folder_options .= $option; + } + clean_sentbox($folder[PRIVMSGS_SENTBOX]['num_messages']); + + // Header for message view - folder and so on + $folder_status = get_folder_status($folder_id, $folder); + + $template->assign_vars(array( + 'CUR_FOLDER_ID' => $folder_id, + 'CUR_FOLDER_NAME' => $folder_status['folder_name'], + 'NUM_NOT_MOVED' => $num_not_moved, + 'NUM_REMOVED' => $num_removed, + 'RELEASE_MESSAGE_INFO' => sprintf($user->lang['RELEASE_MESSAGES'], '<a href="' . $this->u_action . '&folder=' . $folder_id . '&release=1">', '</a>'), + 'NOT_MOVED_MESSAGES' => ($num_not_moved == 1) ? $user->lang['NOT_MOVED_MESSAGE'] : sprintf($user->lang['NOT_MOVED_MESSAGES'], $num_not_moved), + 'RULE_REMOVED_MESSAGES' => ($num_removed == 1) ? $user->lang['RULE_REMOVED_MESSAGE'] : sprintf($user->lang['RULE_REMOVED_MESSAGES'], $num_removed), + + 'S_FOLDER_OPTIONS' => $s_folder_options, + 'S_TO_FOLDER_OPTIONS' => $s_to_folder_options, + 'S_FOLDER_ACTION' => $this->u_action . '&action=view_folder', + 'S_PM_ACTION' => $this->u_action . '&action=' . $action, + + 'U_INBOX' => $this->u_action . '&folder=inbox', + 'U_OUTBOX' => $this->u_action . '&folder=outbox', + 'U_SENTBOX' => $this->u_action . '&folder=sentbox', + 'U_CREATE_FOLDER' => $this->u_action . '&mode=options', + 'U_CURRENT_FOLDER' => $this->u_action . '&folder=' . $folder_id, + + 'S_IN_INBOX' => ($folder_id == PRIVMSGS_INBOX) ? true : false, + 'S_IN_OUTBOX' => ($folder_id == PRIVMSGS_OUTBOX) ? true : false, + 'S_IN_SENTBOX' => ($folder_id == PRIVMSGS_SENTBOX) ? true : false, + + 'FOLDER_STATUS' => $folder_status['message'], + 'FOLDER_MAX_MESSAGES' => $folder_status['max'], + 'FOLDER_CUR_MESSAGES' => $folder_status['cur'], + 'FOLDER_REMAINING_MESSAGES' => $folder_status['remaining'], + 'FOLDER_PERCENT' => $folder_status['percent']) + ); + + if ($action == 'view_folder') + { + include(PHPBB_ROOT_PATH . 'includes/ucp/ucp_pm_viewfolder.' . PHP_EXT); + view_folder($id, $mode, $folder_id, $folder); + + $tpl_file = 'ucp_pm_viewfolder'; + } + else if ($action == 'view_message') + { + $template->assign_vars(array( + 'S_VIEW_MESSAGE' => true, + 'MSG_ID' => $msg_id) + ); + + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + include(PHPBB_ROOT_PATH . 'includes/ucp/ucp_pm_viewmessage.' . PHP_EXT); + view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row); + + $tpl_file = ($view == 'print') ? 'ucp_pm_viewmessage_print' : 'ucp_pm_viewmessage'; + } + + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PM_' . strtoupper($mode)], + 'S_UCP_ACTION' => $this->u_action . ((isset($action)) ? "&action=$action" : '')) + ); + + // Set desired template + $this->tpl_name = $tpl_file; + $this->page_title = 'UCP_PM_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_pm_compose.php b/phpBB/modules/ucp/ucp_pm_compose.php new file mode 100644 index 0000000000..9a540ad22c --- /dev/null +++ b/phpBB/modules/ucp/ucp_pm_compose.php @@ -0,0 +1,1259 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Compose private message +* Called from ucp_pm with mode == 'compose' +*/ +function compose_pm($id, $mode, $action) +{ + global $template, $db, $auth, $user, $config; + + // Damn php and globals - i know, this is horrible + // Needed for handle_message_list_actions() + global $refresh, $submit, $preview; + + include(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/message_parser.' . PHP_EXT); + + if (!$action) + { + $action = 'post'; + } + add_form_key('ucp_pm_compose'); + + // Grab only parameters needed here + $to_user_id = request_var('u', 0); + $to_group_id = request_var('g', 0); + $msg_id = request_var('p', 0); + $draft_id = request_var('d', 0); + $lastclick = request_var('lastclick', 0); + $address_list = request_var('address_list', array('' => array(0 => ''))); + + $submit = request::is_set_post('post'); + $preview = request::is_set_post('preview'); + $save = request::is_set_post('save'); + $load = request::is_set_post('load'); + $cancel = (request::is_set_post('cancel') && !$save) ? true : false; + $delete = request::is_set_post('delete'); + + $remove_u = request::is_set('remove_u'); + $remove_g = request::is_set('remove_g'); + $add_to = request::is_set('add_to'); + $add_bcc = request::is_set('add_bcc'); + + $refresh = request::is_set_post('add_file') || request::is_set_post('delete_file') || $save || $load + || $remove_u || $remove_g || $add_to || $add_bcc; + + $action = ($delete && !$preview && !$refresh && $submit) ? 'delete' : $action; + $select_single = ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? false : true; + + $error = array(); + $current_time = time(); + + // Was cancel pressed? If so then redirect to the appropriate page + if ($cancel || ($current_time - $lastclick < 2 && $submit)) + { + if ($msg_id) + { + redirect(append_sid('ucp', 'i=pm&mode=view&action=view_message&p=' . $msg_id)); + } + redirect(append_sid('ucp', 'i=pm')); + } + + // Output PM_TO box if message composing + if ($action != 'edit') + { + // Add groups to PM box + if ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) + { + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g'; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')'; + } + + $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND '; + + $sql .= 'g.group_receive_pm = 1 + ORDER BY g.group_type DESC, g.group_name ASC'; + $result = $db->sql_query($sql); + + $group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '">' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + } + + $template->assign_vars(array( + 'S_SHOW_PM_BOX' => true, + 'S_ALLOW_MASS_PM' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm')) ? true : false, + 'S_GROUP_OPTIONS' => ($config['allow_mass_pm'] && $auth->acl_get('u_masspm_group')) ? $group_options : '', + 'U_FIND_USERNAME' => append_sid('memberlist', "mode=searchuser&form=postform&field=username_list&select_single=$select_single"), + )); + } + + $sql = ''; + + // What is all this following SQL for? Well, we need to know + // some basic information in all cases before we do anything. + switch ($action) + { + case 'post': + if (!$auth->acl_get('u_sendpm')) + { + trigger_error('NO_AUTH_SEND_MESSAGE'); + } + break; + + case 'reply': + case 'quote': + case 'forward': + case 'quotepost': + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + if (!$auth->acl_get('u_sendpm')) + { + trigger_error('NO_AUTH_SEND_MESSAGE'); + } + + if ($action == 'quotepost') + { + $sql = 'SELECT p.post_id as msg_id, p.forum_id, p.post_text as message_text, p.poster_id as author_id, p.post_time as message_time, p.bbcode_bitfield, p.bbcode_uid, p.enable_sig, p.enable_smilies, p.enable_magic_url, t.topic_title as message_subject, u.username as quote_username + FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t, ' . USERS_TABLE . " u + WHERE p.post_id = $msg_id + AND t.topic_id = p.topic_id + AND u.user_id = p.poster_id"; + } + else + { + $sql = 'SELECT t.folder_id, p.*, u.username as quote_username + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.msg_id = p.msg_id + AND p.msg_id = $msg_id"; + } + break; + + case 'edit': + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + // check for outbox (not read) status, we do not allow editing if one user already having the message + $sql = 'SELECT p.*, t.folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p + WHERE t.user_id = ' . $user->data['user_id'] . ' + AND t.folder_id = ' . PRIVMSGS_OUTBOX . " + AND t.msg_id = $msg_id + AND t.msg_id = p.msg_id"; + break; + + case 'delete': + if (!$auth->acl_get('u_pm_delete')) + { + trigger_error('NO_AUTH_DELETE_MESSAGE'); + } + + if (!$msg_id) + { + trigger_error('NO_MESSAGE'); + } + + $sql = 'SELECT msg_id, pm_unread, pm_new, author_id, folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND msg_id = $msg_id"; + break; + + case 'smilies': + generate_smilies('window', 0); + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + if ($action == 'forward' && (!$config['forward_pm'] || !$auth->acl_get('u_pm_forward'))) + { + trigger_error('NO_AUTH_FORWARD_MESSAGE'); + } + + if ($action == 'edit' && !$auth->acl_get('u_pm_edit')) + { + trigger_error('NO_AUTH_EDIT_MESSAGE'); + } + + if ($sql) + { + $result = $db->sql_query($sql); + $post = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$post) + { + // If editing it could be the recipient already read the message... + if ($action == 'edit') + { + $sql = 'SELECT p.*, t.folder_id + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p + WHERE t.user_id = ' . $user->data['user_id'] . " + AND t.msg_id = $msg_id + AND t.msg_id = p.msg_id"; + $result = $db->sql_query($sql); + $post = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($post) + { + trigger_error('NO_EDIT_READ_MESSAGE'); + } + } + + trigger_error('NO_MESSAGE'); + } + + if ($action == 'quotepost') + { + if (($post['forum_id'] && !$auth->acl_get('f_read', $post['forum_id'])) || (!$post['forum_id'] && !$auth->acl_getf_global('f_read'))) + { + trigger_error('NOT_AUTHORISED'); + } + + // Passworded forum? + if ($post['forum_id']) + { + $sql = 'SELECT forum_password + FROM ' . FORUMS_TABLE . ' + WHERE forum_id = ' . (int) $post['forum_id']; + $result = $db->sql_query($sql); + $forum_password = (string) $db->sql_fetchfield('forum_password'); + $db->sql_freeresult($result); + + if ($forum_password) + { + login_forum_box(array( + 'forum_id' => $post['forum_id'], + 'forum_password' => $forum_password, + )); + } + } + } + + $msg_id = (int) $post['msg_id']; + $folder_id = (isset($post['folder_id'])) ? $post['folder_id'] : 0; + $message_text = (isset($post['message_text'])) ? $post['message_text'] : ''; + + if ((!$post['author_id'] || ($post['author_id'] == ANONYMOUS && $action != 'delete')) && $msg_id) + { + trigger_error('NO_AUTHOR'); + } + + if ($action == 'quotepost') + { + // Decode text for message display + decode_message($message_text, $post['bbcode_uid']); + } + + if ($action != 'delete') + { + $enable_urls = $post['enable_magic_url']; + $enable_sig = (isset($post['enable_sig'])) ? $post['enable_sig'] : 0; + + $message_attachment = (isset($post['message_attachment'])) ? $post['message_attachment'] : 0; + $message_subject = $post['message_subject']; + $message_time = $post['message_time']; + $bbcode_uid = $post['bbcode_uid']; + + $quote_username = (isset($post['quote_username'])) ? $post['quote_username'] : ''; + $icon_id = (isset($post['icon_id'])) ? $post['icon_id'] : 0; + + if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !sizeof($address_list) && !$refresh && !$submit && !$preview) + { + if ($action == 'quotepost') + { + $address_list = array('u' => array($post['author_id'] => 'to')); + } + else + { + // We try to include every previously listed member from the TO Header + $address_list = rebuild_header(array('to' => $post['to_address'])); + + // Add the author (if he is already listed then this is no shame (it will be overwritten)) + $address_list['u'][$post['author_id']] = 'to'; + + // Now, make sure the user itself is not listed. ;) + if (isset($address_list['u'][$user->data['user_id']])) + { + unset($address_list['u'][$user->data['user_id']]); + } + } + } + else if ($action == 'edit' && !sizeof($address_list) && !$refresh && !$submit && !$preview) + { + // Rebuild TO and BCC Header + $address_list = rebuild_header(array('to' => $post['to_address'], 'bcc' => $post['bcc_address'])); + } + + if ($action == 'quotepost') + { + $check_value = 0; + } + else + { + $check_value = (($post['enable_bbcode']+1) << 8) + (($post['enable_smilies']+1) << 4) + (($enable_urls+1) << 2) + (($post['enable_sig']+1) << 1); + } + } + } + else + { + $message_attachment = 0; + $message_text = $message_subject = ''; + + if ($to_user_id && $action == 'post') + { + $address_list['u'][$to_user_id] = 'to'; + } + else if ($to_group_id && $action == 'post') + { + $address_list['g'][$to_group_id] = 'to'; + } + $check_value = 0; + } + + if (($to_group_id || isset($address_list['g'])) && (!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group'))) + { + trigger_error('NO_AUTH_GROUP_MESSAGE'); + } + + if ($action == 'edit' && !$refresh && !$preview && !$submit) + { + if (!($message_time > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time'])) + { + trigger_error('CANNOT_EDIT_MESSAGE_TIME'); + } + } + + if ($action == 'post') + { + $template->assign_var('S_NEW_MESSAGE', true); + } + + if (!isset($icon_id)) + { + $icon_id = 0; + } + + $message_parser = new parse_message(); + + $message_parser->message = ($action == 'reply') ? '' : $message_text; + unset($message_text); + + $s_action = append_sid('ucp', "i=$id&mode=$mode&action=$action", true, $user->session_id); + $s_action .= ($msg_id) ? "&p=$msg_id" : ''; + + // Delete triggered ? + if ($action == 'delete') + { + // Folder id has been determined by the SQL Statement + // $folder_id = request_var('f', PRIVMSGS_NO_BOX); + + // Do we need to confirm ? + if (confirm_box(true)) + { + delete_pm($user->data['user_id'], $msg_id, $folder_id); + + // jump to next message in "history"? nope, not for the moment. But able to be included later. + $meta_info = append_sid('ucp', "i=pm&folder=$folder_id"); + $message = $user->lang['MESSAGE_DELETED']; + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + $s_hidden_fields = array( + 'p' => $msg_id, + 'f' => $folder_id, + 'action' => 'delete' + ); + + // "ucp.php?i=pm&mode=compose" + confirm_box(false, 'DELETE_MESSAGE', build_hidden_fields($s_hidden_fields)); + } + + redirect(append_sid('ucp', 'i=pm&mode=view&action=view_message&p=' . $msg_id)); + } + + // Get maximum number of allowed recipients + $sql = 'SELECT MAX(g.group_max_recipients) as max_recipients + FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug + WHERE ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + AND ug.group_id = g.group_id'; + $result = $db->sql_query($sql); + $max_recipients = (int) $db->sql_fetchfield('max_recipients'); + $db->sql_freeresult($result); + + $max_recipients = (!$max_recipients) ? $config['pm_max_recipients'] : $max_recipients; + + // If this is a quote/reply "to all"... we may increase the max_recpients to the number of original recipients + if (($action == 'reply' || $action == 'quote') && $max_recipients) + { + // We try to include every previously listed member from the TO Header + $list = rebuild_header(array('to' => $post['to_address'])); + + // Can be an empty array too ;) + $list = (!empty($list['u'])) ? $list['u'] : array(); + $list[$post['author_id']] = 'to'; + + if (isset($list[$user->data['user_id']])) + { + unset($list[$user->data['user_id']]); + } + + $max_recipients = ($max_recipients < sizeof($list)) ? sizeof($list) : $max_recipients; + + unset($list); + } + + // Handle User/Group adding/removing + handle_message_list_actions($address_list, $error, $remove_u, $remove_g, $add_to, $add_bcc); + + // Check mass pm to group permission + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm_group')) && !empty($address_list['g'])) + { + $address_list = array(); + $error[] = $user->lang['NO_AUTH_GROUP_MESSAGE']; + } + + // Check mass pm to users permission + if ((!$config['allow_mass_pm'] || !$auth->acl_get('u_masspm')) && num_recipients($address_list) > 1) + { + $address_list = get_recipients($address_list, 1); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', 1); + } + + // Check for too many recipients + if (!empty($address_list['u']) && $max_recipients && sizeof($address_list['u']) > $max_recipients) + { + $address_list = get_recipients($address_list, $max_recipients); + $error[] = $user->lang('TOO_MANY_RECIPIENTS', $max_recipients); + } + + // Always check if the submitted attachment data is valid and belongs to the user. + // Further down (especially in submit_post()) we do not check this again. + $message_parser->get_submitted_attachment_data(); + + if ($message_attachment && !$submit && !$refresh && !$preview && $action == 'edit') + { + // Do not change to SELECT * + $sql = 'SELECT attach_id, is_orphan, attach_comment, real_filename + FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = $msg_id + AND in_message = 1 + AND is_orphan = 0 + ORDER BY filetime DESC"; + $result = $db->sql_query($sql); + $message_parser->attachment_data = array_merge($message_parser->attachment_data, $db->sql_fetchrowset($result)); + $db->sql_freeresult($result); + } + + if (!in_array($action, array('quote', 'edit', 'delete', 'forward'))) + { + $enable_sig = ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig') && $user->optionget('attachsig')); + $enable_smilies = ($config['allow_smilies'] && $auth->acl_get('u_pm_smilies') && $user->optionget('smilies')); + $enable_bbcode = ($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode') && $user->optionget('bbcode')); + $enable_urls = true; + } + + $enable_magic_url = $drafts = false; + + // User own some drafts? + if ($auth->acl_get('u_savedrafts') && $action != 'delete') + { + $sql = 'SELECT draft_id + FROM ' . DRAFTS_TABLE . ' + WHERE forum_id = 0 + AND topic_id = 0 + AND user_id = ' . $user->data['user_id'] . + (($draft_id) ? " AND draft_id <> $draft_id" : ''); + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + $drafts = true; + } + } + + if ($action == 'edit') + { + $message_parser->bbcode_uid = $bbcode_uid; + } + + $bbcode_status = ($config['allow_bbcode'] && $config['auth_bbcode_pm'] && $auth->acl_get('u_pm_bbcode')) ? true : false; + $smilies_status = ($config['allow_smilies'] && $config['auth_smilies_pm'] && $auth->acl_get('u_pm_smilies')) ? true : false; + $img_status = ($config['auth_img_pm'] && $auth->acl_get('u_pm_img')) ? true : false; + $flash_status = ($config['auth_flash_pm'] && $auth->acl_get('u_pm_flash')) ? true : false; + $url_status = ($config['allow_post_links']) ? true : false; + + // Save Draft + if ($save && $auth->acl_get('u_savedrafts')) + { + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $subject = (!$subject && $action != 'post') ? $user->lang['NEW_MESSAGE'] : $subject; + $message = utf8_normalize_nfc(request_var('message', '', true)); + + if ($subject && $message) + { + if (confirm_box(true)) + { + $sql = 'INSERT INTO ' . DRAFTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => $user->data['user_id'], + 'topic_id' => 0, + 'forum_id' => 0, + 'save_time' => $current_time, + 'draft_subject' => $subject, + 'draft_message' => $message + ) + ); + $db->sql_query($sql); + + $redirect_url = append_sid('ucp', "i=pm&mode=$mode"); + + meta_refresh(3, $redirect_url); + $message = $user->lang['DRAFT_SAVED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + + trigger_error($message); + } + else + { + $s_hidden_fields = build_hidden_fields(array( + 'mode' => $mode, + 'action' => $action, + 'save' => true, + 'subject' => $subject, + 'message' => $message, + 'u' => $to_user_id, + 'g' => $to_group_id, + 'p' => $msg_id) + ); + $s_hidden_fields .= build_address_field($address_list); + + + confirm_box(false, 'SAVE_DRAFT', $s_hidden_fields); + } + } + else + { + if (utf8_clean_string($subject) === '') + { + $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT']; + } + + if (utf8_clean_string($message) === '') + { + $error[] = $user->lang['TOO_FEW_CHARS']; + } + } + + unset($subject, $message); + } + + // Load Draft + if ($draft_id && $auth->acl_get('u_savedrafts')) + { + $sql = 'SELECT draft_subject, draft_message + FROM ' . DRAFTS_TABLE . " + WHERE draft_id = $draft_id + AND topic_id = 0 + AND forum_id = 0 + AND user_id = " . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + + if ($row = $db->sql_fetchrow($result)) + { + $message_parser->message = $row['draft_message']; + $message_subject = $row['draft_subject']; + + $template->assign_var('S_DRAFT_LOADED', true); + } + else + { + $draft_id = 0; + } + $db->sql_freeresult($result); + } + + // Load Drafts + if ($load && $drafts) + { + load_drafts(0, 0, $id); + } + + if ($submit || $preview || $refresh) + { + if (($submit || $preview) && !check_form_key('ucp_pm_compose')) + { + $error[] = $user->lang['FORM_INVALID']; + } + $subject = utf8_normalize_nfc(request_var('subject', '', true)); + $message_parser->message = utf8_normalize_nfc(request_var('message', '', true)); + + $icon_id = request_var('icon', 0); + + $enable_bbcode = (!$bbcode_status || request::is_set_post('disable_bbcode')) ? false : true; + $enable_smilies = (!$smilies_status || request::is_set_post'disable_smilies')) ? false : true; + $enable_urls = (request::is_set_post('disable_magic_url')) ? 0 : 1; + $enable_sig = (!$config['allow_sig'] ||!$config['allow_sig_pm']) ? false : request::is_set_post('attach_sig'); + + if ($submit) + { + $status_switch = (($enable_bbcode+1) << 8) + (($enable_smilies+1) << 4) + (($enable_urls+1) << 2) + (($enable_sig+1) << 1); + $status_switch = ($status_switch != $check_value); + } + else + { + $status_switch = 1; + } + + // Parse Attachments - before checksum is calculated + $message_parser->parse_attachments('fileupload', $action, 0, $submit, $preview, $refresh, true); + + if (sizeof($message_parser->warn_msg) && !($remove_u || $remove_g || $add_to || $add_bcc)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + $message_parser->warn_msg = array(); + } + + // Parse message + $message_parser->parse($enable_bbcode, ($config['allow_post_links']) ? $enable_urls : false, $enable_smilies, $img_status, $flash_status, true, $config['allow_post_links']); + + // On a refresh we do not care about message parsing errors + if (sizeof($message_parser->warn_msg) && !$refresh) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if ($action != 'edit' && !$preview && !$refresh && $config['flood_interval'] && !$auth->acl_get('u_ignoreflood')) + { + // Flood check + $last_post_time = $user->data['user_lastpost_time']; + + if ($last_post_time) + { + if ($last_post_time && ($current_time - $last_post_time) < intval($config['flood_interval'])) + { + $error[] = $user->lang['FLOOD_ERROR']; + } + } + } + + // Subject defined + if ($submit) + { + if (utf8_clean_string($subject) === '') + { + $error[] = $user->lang['EMPTY_MESSAGE_SUBJECT']; + } + + if (!sizeof($address_list)) + { + $error[] = $user->lang['NO_RECIPIENT']; + } + } + + // Store message, sync counters + if (!sizeof($error) && $submit) + { + $pm_data = array( + 'msg_id' => (int) $msg_id, + 'from_user_id' => $user->data['user_id'], + 'from_user_ip' => $user->ip, + 'from_username' => $user->data['username'], + 'reply_from_root_level' => (isset($post['root_level'])) ? (int) $post['root_level'] : 0, + 'reply_from_msg_id' => (int) $msg_id, + 'icon_id' => (int) $icon_id, + 'enable_sig' => (bool) $enable_sig, + 'enable_bbcode' => (bool) $enable_bbcode, + 'enable_smilies' => (bool) $enable_smilies, + 'enable_urls' => (bool) $enable_urls, + 'bbcode_bitfield' => $message_parser->bbcode_bitfield, + 'bbcode_uid' => $message_parser->bbcode_uid, + 'message' => $message_parser->message, + 'attachment_data' => $message_parser->attachment_data, + 'filename_data' => $message_parser->filename_data, + 'address_list' => $address_list + ); + + // ((!$message_subject) ? $subject : $message_subject) + $msg_id = submit_pm($action, $subject, $pm_data); + + $return_message_url = append_sid('ucp', 'i=pm&mode=view&p=' . $msg_id); + $return_folder_url = append_sid('ucp', 'i=pm&folder=outbox'); + meta_refresh(3, $return_message_url); + + $message = $user->lang['MESSAGE_STORED'] . '<br /><br />' . sprintf($user->lang['VIEW_PRIVATE_MESSAGE'], '<a href="' . $return_message_url . '">', '</a>') . '<br /><br />' . sprintf($user->lang['CLICK_RETURN_FOLDER'], '<a href="' . $return_folder_url . '">', '</a>', $user->lang['PM_OUTBOX']); + trigger_error($message); + } + + $message_subject = $subject; + } + + // Preview + if (!sizeof($error) && $preview) + { + $user->add_lang('viewtopic'); + $preview_message = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + + $preview_signature = $user->data['user_sig']; + $preview_signature_uid = $user->data['user_sig_bbcode_uid']; + $preview_signature_bitfield = $user->data['user_sig_bbcode_bitfield']; + + // Signature + if ($enable_sig && $config['allow_sig'] && $preview_signature) + { + $parse_sig = new parse_message($preview_signature); + $parse_sig->bbcode_uid = $preview_signature_uid; + $parse_sig->bbcode_bitfield = $preview_signature_bitfield; + + $parse_sig->format_display($enable_bbcode, $enable_urls, $enable_smilies); + $preview_signature = $parse_sig->message; + unset($parse_sig); + } + else + { + $preview_signature = ''; + } + + // Attachment Preview + if (sizeof($message_parser->attachment_data)) + { + $template->assign_var('S_HAS_ATTACHMENTS', true); + + $update_count = array(); + $attachment_data = $message_parser->attachment_data; + + parse_attachments(false, $preview_message, $attachment_data, $update_count, true); + + foreach ($attachment_data as $i => $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + unset($attachment_data); + } + + $preview_subject = censor_text($subject); + + if (!sizeof($error)) + { + $template->assign_vars(array( + 'PREVIEW_SUBJECT' => $preview_subject, + 'PREVIEW_MESSAGE' => $preview_message, + 'PREVIEW_SIGNATURE' => $preview_signature, + + 'S_DISPLAY_PREVIEW' => true) + ); + } + unset($message_text); + } + + // Decode text for message display + $bbcode_uid = (($action == 'quote' || $action == 'forward') && !$preview && !$refresh && !sizeof($error)) ? $bbcode_uid : $message_parser->bbcode_uid; + + $message_parser->decode_message($bbcode_uid); + + if (($action == 'quote' || $action == 'quotepost') && !$preview && !$refresh && !$submit) + { + if ($action == 'quotepost') + { + $post_id = request_var('p', 0); + if ($config['allow_post_links']) + { + $message_link = "[url=" . generate_board_url() . '/viewtopic.' . PHP_EXT . "?p={$post_id}#p{$post_id}]{$user->lang['SUBJECT']}: {$message_subject}[/url]\n\n"; + } + else + { + $message_link = $user->lang['SUBJECT'] . ': ' . $message_subject . " (" . generate_board_url() . '/viewtopic.' . PHP_EXT . "?p={$post_id}#p{$post_id})\n\n"; + } + } + else + { + $message_link = ''; + } + $message_parser->message = $message_link . '[quote="' . $quote_username . '"]' . censor_text(trim($message_parser->message)) . "[/quote]\n"; + } + + if (($action == 'reply' || $action == 'quote' || $action == 'quotepost') && !$preview && !$refresh) + { + $message_subject = ((!preg_match('/^Re:/', $message_subject)) ? 'Re: ' : '') . censor_text($message_subject); + } + + if ($action == 'forward' && !$preview && !$refresh && !$submit) + { + $fwd_to_field = write_pm_addresses(array('to' => $post['to_address']), 0, true); + + if ($config['allow_post_links']) + { + $quote_username_text = '[url=' . generate_board_url() . '/memberlist.' . PHP_EXT . "?mode=viewprofile&u={$post['author_id']}]{$quote_username}[/url]"; + } + else + { + $quote_username_text = $quote_username . ' (' . generate_board_url() . '/memberlist.' . PHP_EXT . "?mode=viewprofile&u={$post['author_id']})"; + } + + $forward_text = array(); + $forward_text[] = $user->lang['FWD_ORIGINAL_MESSAGE']; + $forward_text[] = sprintf($user->lang['FWD_SUBJECT'], censor_text($message_subject)); + $forward_text[] = sprintf($user->lang['FWD_DATE'], $user->format_date($message_time)); + $forward_text[] = sprintf($user->lang['FWD_FROM'], $quote_username_text); + $forward_text[] = sprintf($user->lang['FWD_TO'], implode(', ', $fwd_to_field['to'])); + + $message_parser->message = implode("\n", $forward_text) . "\n\n[quote="{$quote_username}"]\n" . censor_text(trim($message_parser->message)) . "\n[/quote]"; + $message_subject = ((!preg_match('/^Fwd:/', $message_subject)) ? 'Fwd: ' : '') . censor_text($message_subject); + } + + $attachment_data = $message_parser->attachment_data; + $filename_data = $message_parser->filename_data; + $message_text = $message_parser->message; + + // MAIN PM PAGE BEGINS HERE + + // Generate smiley listing + generate_smilies('inline', 0); + + // Generate PM Icons + $s_pm_icons = false; + if ($config['enable_pm_icons']) + { + $s_pm_icons = posting_gen_topic_icons($action, $icon_id); + } + + // Generate inline attachment select box + posting_gen_inline_attachments($attachment_data); + + // Build address list for display + // array('u' => array($author_id => 'to')); + if (sizeof($address_list)) + { + // Get Usernames and Group Names + $result = array(); + if (!empty($address_list['u'])) + { + $sql = 'SELECT user_id as id, username as name, user_colour as colour + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($address_list['u']))) . ' + ORDER BY username_clean ASC'; + $result['u'] = $db->sql_query($sql); + } + + if (!empty($address_list['g'])) + { + $sql = 'SELECT g.group_id AS id, g.group_name AS name, g.group_colour AS colour, g.group_type + FROM ' . GROUPS_TABLE . ' g'; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= ' LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (g.group_type <> ' . GROUP_HIDDEN . ' OR ug.user_id = ' . $user->data['user_id'] . ')'; + } + + $sql .= ($auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) ? ' WHERE ' : ' AND '; + + $sql .= 'g.group_receive_pm = 1 + AND ' . $db->sql_in_set('g.group_id', array_map('intval', array_keys($address_list['g']))) . ' + ORDER BY g.group_name ASC'; + + $result['g'] = $db->sql_query($sql); + } + + $u = $g = array(); + $_types = array('u', 'g'); + foreach ($_types as $type) + { + if (isset($result[$type]) && $result[$type]) + { + while ($row = $db->sql_fetchrow($result[$type])) + { + if ($type == 'g') + { + $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + } + + ${$type}[$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); + } + $db->sql_freeresult($result[$type]); + } + } + + // Now Build the address list + $plain_address_field = ''; + foreach ($address_list as $type => $adr_ary) + { + foreach ($adr_ary as $id => $field) + { + if (!isset(${$type}[$id])) + { + unset($address_list[$type][$id]); + continue; + } + + $field = ($field == 'to') ? 'to' : 'bcc'; + $type = ($type == 'u') ? 'u' : 'g'; + $id = (int) $id; + + $tpl_ary = array( + 'IS_GROUP' => ($type == 'g') ? true : false, + 'IS_USER' => ($type == 'u') ? true : false, + 'UG_ID' => $id, + 'NAME' => ${$type}[$id]['name'], + 'COLOUR' => (${$type}[$id]['colour']) ? '#' . ${$type}[$id]['colour'] : '', + 'TYPE' => $type, + ); + + if ($type == 'u') + { + $tpl_ary = array_merge($tpl_ary, array( + 'U_VIEW' => get_username_string('profile', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']), + 'NAME_FULL' => get_username_string('full', $id, ${$type}[$id]['name'], ${$type}[$id]['colour']), + )); + } + else + { + $tpl_ary = array_merge($tpl_ary, array( + 'U_VIEW' => append_sid('memberlist', 'mode=group&g=' . $id), + )); + } + + $template->assign_block_vars($field . '_recipient', $tpl_ary); + } + } + } + + // Build hidden address list + $s_hidden_address_field = build_address_field($address_list); + + + $bbcode_checked = (isset($enable_bbcode)) ? !$enable_bbcode : (($config['allow_bbcode'] && $auth->acl_get('u_pm_bbcode')) ? !$user->optionget('bbcode') : 1); + $smilies_checked = (isset($enable_smilies)) ? !$enable_smilies : (($config['allow_smilies'] && $auth->acl_get('u_pm_smilies')) ? !$user->optionget('smilies') : 1); + $urls_checked = (isset($enable_urls)) ? !$enable_urls : 0; + $sig_checked = $enable_sig; + + switch ($action) + { + case 'post': + $page_title = $user->lang['POST_NEW_PM']; + break; + + case 'quote': + $page_title = $user->lang['POST_QUOTE_PM']; + break; + + case 'quotepost': + $page_title = $user->lang['POST_PM_POST']; + break; + + case 'reply': + $page_title = $user->lang['POST_REPLY_PM']; + break; + + case 'edit': + $page_title = $user->lang['POST_EDIT_PM']; + break; + + case 'forward': + $page_title = $user->lang['POST_FORWARD_PM']; + break; + + default: + trigger_error('NO_ACTION_MODE', E_USER_ERROR); + break; + } + + $s_hidden_fields = '<input type="hidden" name="lastclick" value="' . $current_time . '" />'; + $s_hidden_fields .= (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : ''; + $s_hidden_fields .= ($draft_id || request::is_set('draft_loaded')) ? '<input type="hidden" name="draft_loaded" value="' . request_var('draft_loaded', (int) $draft_id) . '" />' : ''; + + $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; + + // Start assigning vars for main posting page ... + $template->assign_vars(array( + 'L_POST_A' => $page_title, + 'L_ICON' => $user->lang['PM_ICON'], + 'L_MESSAGE_BODY_EXPLAIN' => (intval($config['max_post_chars'])) ? sprintf($user->lang['MESSAGE_BODY_EXPLAIN'], intval($config['max_post_chars'])) : '', + + 'SUBJECT' => (isset($message_subject)) ? $message_subject : '', + 'MESSAGE' => $message_text, + 'BBCODE_STATUS' => ($bbcode_status) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>'), + 'IMG_STATUS' => ($img_status) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($flash_status) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'SMILIES_STATUS' => ($smilies_status) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'URL_STATUS' => ($url_status) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'MAX_RECIPIENTS' => ($config['allow_mass_pm'] && ($auth->acl_get('u_masspm') || $auth->acl_get('u_masspm_group'))) ? $max_recipients : 0, + + 'S_COMPOSE_PM' => true, + 'S_EDIT_POST' => ($action == 'edit'), + 'S_SHOW_PM_ICONS' => $s_pm_icons, + 'S_BBCODE_ALLOWED' => $bbcode_status, + 'S_BBCODE_CHECKED' => ($bbcode_checked) ? ' checked="checked"' : '', + 'S_SMILIES_ALLOWED' => $smilies_status, + 'S_SMILIES_CHECKED' => ($smilies_checked) ? ' checked="checked"' : '', + 'S_SIG_ALLOWED' => ($config['allow_sig'] && $config['allow_sig_pm'] && $auth->acl_get('u_sig')), + 'S_SIGNATURE_CHECKED' => ($sig_checked) ? ' checked="checked"' : '', + 'S_LINKS_ALLOWED' => $url_status, + 'S_MAGIC_URL_CHECKED' => ($urls_checked) ? ' checked="checked"' : '', + 'S_SAVE_ALLOWED' => ($auth->acl_get('u_savedrafts') && $action != 'edit') ? true : false, + 'S_HAS_DRAFTS' => ($auth->acl_get('u_savedrafts') && $drafts), + 'S_FORM_ENCTYPE' => $form_enctype, + + 'S_BBCODE_IMG' => $img_status, + 'S_BBCODE_FLASH' => $flash_status, + 'S_BBCODE_QUOTE' => true, + 'S_BBCODE_URL' => $url_status, + + 'S_POST_ACTION' => $s_action, + 'S_HIDDEN_ADDRESS_FIELD' => $s_hidden_address_field, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + + 'S_CLOSE_PROGRESS_WINDOW' => request::is_set_post('add_file'), + 'U_PROGRESS_BAR' => append_sid('posting', 'f=0&mode=popup'), + 'UA_PROGRESS_BAR' => addslashes(append_sid('posting', 'f=0&mode=popup')), + )); + + // Build custom bbcodes array + display_custom_bbcodes(); + + // Show attachment box for adding attachments if true + $allowed = ($auth->acl_get('u_pm_attach') && $config['allow_pm_attach'] && $form_enctype); + + // Attachment entry + posting_gen_attachment_entry($attachment_data, $filename_data, $allowed); + + // Message History + if ($action == 'reply' || $action == 'quote' || $action == 'forward') + { + if (message_history($msg_id, $user->data['user_id'], $post, array(), true)) + { + $template->assign_var('S_DISPLAY_HISTORY', true); + } + } +} + +/** +* For composing messages, handle list actions +*/ +function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove_g, $add_to, $add_bcc) +{ + global $auth, $db, $user; + + // Delete User [TO/BCC] + $remove_user_id = request_var('remove_u', array(0 => false)); + if ($remove_u && sizeof($remove_user_id)) + { + unset($address_list['u'][(int) key($remove_user_id)]); + } + + // Delete Group [TO/BCC] + $remove_group_id = request_var('remove_g', array(0 => false)); + if ($remove_g && sizeof($remove_group_id)) + { + unset($address_list['g'][(int) key($remove_group_id)]); + } + + // Add Selected Groups + $group_list = request_var('group_list', array(0)); + + // Build usernames to add + $username = request_var('username', '', true) + $usernames = ($username) ? array($username) : array(); + $username_list = request_var('username_list', '', true); + if ($username_list) + { + $usernames = array_merge($usernames, explode("\n", $username_list)); + } + + // If add to or add bcc not pressed, users could still have usernames listed they want to add... + if (!$add_to && !$add_bcc && (sizeof($group_list) || sizeof($usernames))) + { + $add_to = true; + + global $refresh, $submit, $preview; + + $refresh = $preview = true; + $submit = false; + } + + // Add User/Group [TO] + if ($add_to || $add_bcc) + { + $type = ($add_to) ? 'to' : 'bcc'; + + if (sizeof($group_list)) + { + foreach ($group_list as $group_id) + { + $address_list['g'][$group_id] = $type; + } + } + + // User ID's to add... + $user_id_ary = array(); + + // Reveal the correct user_ids + if (sizeof($usernames)) + { + $user_id_ary = array(); + user_get_id_name($user_id_ary, $usernames, array(USER_NORMAL, USER_FOUNDER, USER_INACTIVE)); + + // If there are users not existing, we will at least print a notice... + if (!sizeof($user_id_ary)) + { + $error[] = $user->lang['PM_NO_USERS']; + } + } + + // Add Friends if specified + $friend_list = array_keys(request_var('add_' . $type, array(0 => false))); + $user_id_ary = array_merge($user_id_ary, $friend_list); + + foreach ($user_id_ary as $user_id) + { + if ($user_id == ANONYMOUS) + { + continue; + } + + $address_list['u'][$user_id] = $type; + } + } + + // Check for disallowed recipients + if (!empty($address_list['u'])) + { + // We need to check their PM status (do they want to receive PM's?) + // Only check if not a moderator or admin, since they are allowed to override this user setting + if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_')) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', array_keys($address_list['u'])) . ' + AND user_allow_pm = 0'; + $result = $db->sql_query($sql); + + $removed = false; + while ($row = $db->sql_fetchrow($result)) + { + $removed = true; + unset($address_list['u'][$row['user_id']]); + } + $db->sql_freeresult($result); + + // print a notice about users not being added who do not want to receive pms + if ($removed) + { + $error[] = $user->lang['PM_USERS_REMOVED_NO_PM']; + } + } + } +} + +/** +* Build the hidden field for the recipients. Needed, as the variable is not read via request_var. +*/ +function build_address_field($address_list) +{ + $s_hidden_address_field = ''; + foreach ($address_list as $type => $adr_ary) + { + foreach ($adr_ary as $id => $field) + { + $s_hidden_address_field .= '<input type="hidden" name="address_list[' . (($type == 'u') ? 'u' : 'g') . '][' . (int) $id . ']" value="' . (($field == 'to') ? 'to' : 'bcc') . '" />'; + } + } + return $s_hidden_address_field; +} + +/** +* Return number of private message recipients +*/ +function num_recipients($address_list) +{ + $num_recipients = 0; + + foreach ($address_list as $field => $adr_ary) + { + $num_recipients += sizeof($adr_ary); + } + + return $num_recipients; +} + +/** +* Get number of 'num_recipients' recipients from first position +*/ +function get_recipients($address_list, $num_recipients = 1) +{ + $recipient = array(); + + $count = 0; + foreach ($address_list as $field => $adr_ary) + { + foreach ($adr_ary as $id => $type) + { + if ($count >= $num_recipients) + { + break 2; + } + $recipient[$field][$id] = $type; + $count++; + } + } + + return $recipient; +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_pm_options.php b/phpBB/modules/ucp/ucp_pm_options.php new file mode 100644 index 0000000000..af3b211a5e --- /dev/null +++ b/phpBB/modules/ucp/ucp_pm_options.php @@ -0,0 +1,832 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Execute message options +*/ +function message_options($id, $mode, $global_privmsgs_rules, $global_rule_conditions) +{ + global $user, $template, $auth, $config, $db; + + $redirect_url = append_sid('ucp', "i=pm&mode=options"); + + add_form_key('ucp_pm_options'); + // Change "full folder" setting - what to do if folder is full + if (request::is_set_post('fullfolder')) + { + check_form_key('ucp_pm_options', $config['form_token_lifetime'], $redirect_url); + $full_action = request_var('full_action', 0); + + $set_folder_id = 0; + switch ($full_action) + { + case 1: + $set_folder_id = FULL_FOLDER_DELETE; + break; + + case 2: + $set_folder_id = request_var('full_move_to', PRIVMSGS_INBOX); + break; + + case 3: + $set_folder_id = FULL_FOLDER_HOLD; + break; + + default: + $full_action = 0; + break; + } + + if ($full_action) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_full_folder = ' . $set_folder_id . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $user->data['user_full_folder'] = $set_folder_id; + + $message = $user->lang['FULL_FOLDER_OPTION_CHANGED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + } + + // Add Folder + if (request::is_set_post('addfolder')) + { + if (check_form_key('ucp_pm_options')) + { + $folder_name = utf8_normalize_nfc(request_var('foldername', '', true)); + $msg = ''; + + if ($folder_name) + { + $sql = 'SELECT folder_name + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE folder_name = '" . $db->sql_escape($folder_name) . "' + AND user_id = " . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error(sprintf($user->lang['FOLDER_NAME_EXIST'], $folder_name)); + } + + $sql = 'SELECT COUNT(folder_id) as num_folder + FROM ' . PRIVMSGS_FOLDER_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + $num_folder = (int) $db->sql_fetchfield('num_folder'); + $db->sql_freeresult($result); + + if ($num_folder >= $config['pm_max_boxes']) + { + trigger_error('MAX_FOLDER_REACHED'); + } + + $sql = 'INSERT INTO ' . PRIVMSGS_FOLDER_TABLE . ' ' . $db->sql_build_array('INSERT', array( + 'user_id' => (int) $user->data['user_id'], + 'folder_name' => $folder_name) + ); + $db->sql_query($sql); + $msg = $user->lang['FOLDER_ADDED']; + } + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Rename folder + if (request::is_set_post('rename_folder')) + { + if (check_form_key('ucp_pm_options')) + { + $new_folder_name = utf8_normalize_nfc(request_var('new_folder_name', '', true)); + $rename_folder_id= request_var('rename_folder_id', 0); + + if (!$new_folder_name) + { + trigger_error('NO_NEW_FOLDER_NAME'); + } + + // Select custom folder + $sql = 'SELECT folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $rename_folder_id"; + $result = $db->sql_query_limit($sql, 1); + $folder_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$folder_row) + { + trigger_error('CANNOT_RENAME_FOLDER'); + } + + $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " + SET folder_name = '" . $db->sql_escape($new_folder_name) . "' + WHERE folder_id = $rename_folder_id + AND user_id = {$user->data['user_id']}"; + $db->sql_query($sql); + $msg = $user->lang['FOLDER_RENAMED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Remove Folder + if (request::is_set_post('remove_folder')) + { + $remove_folder_id = request_var('remove_folder_id', 0); + + // Default to "move all messages to inbox" + $remove_action = request_var('remove_action', 1); + $move_to = request_var('move_to', PRIVMSGS_INBOX); + + // Move to same folder? + if ($remove_action == 1 && $remove_folder_id == $move_to) + { + trigger_error('CANNOT_MOVE_TO_SAME_FOLDER'); + } + + // Select custom folder + $sql = 'SELECT folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $remove_folder_id"; + $result = $db->sql_query_limit($sql, 1); + $folder_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$folder_row) + { + trigger_error('CANNOT_REMOVE_FOLDER'); + } + + $s_hidden_fields = array( + 'remove_folder_id' => $remove_folder_id, + 'remove_action' => $remove_action, + 'move_to' => $move_to, + 'remove_folder' => 1 + ); + + // Do we need to confirm? + if (confirm_box(true)) + { + // Gather message ids + $sql = 'SELECT msg_id + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND folder_id = $remove_folder_id"; + $result = $db->sql_query($sql); + + $msg_ids = array(); + while ($row = $db->sql_fetchrow($result)) + { + $msg_ids[] = (int) $row['msg_id']; + } + $db->sql_freeresult($result); + + // First of all, copy all messages to another folder... or delete all messages + switch ($remove_action) + { + // Move Messages + case 1: + $num_moved = move_pm($user->data['user_id'], $user->data['message_limit'], $msg_ids, $move_to, $remove_folder_id); + + // Something went wrong, only partially moved? + if ($num_moved != $folder_row['pm_count']) + { + trigger_error(sprintf($user->lang['MOVE_PM_ERROR'], $num_moved, $folder_row['pm_count'])); + } + break; + + // Remove Messages + case 2: + delete_pm($user->data['user_id'], $msg_ids, $remove_folder_id); + break; + } + + // Remove folder + $sql = 'DELETE FROM ' . PRIVMSGS_FOLDER_TABLE . " + WHERE user_id = {$user->data['user_id']} + AND folder_id = $remove_folder_id"; + $db->sql_query($sql); + + // Check full folder option. If the removed folder has been specified as destination switch back to inbox + if ($user->data['user_full_folder'] == $remove_folder_id) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_full_folder = ' . PRIVMSGS_INBOX . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $user->data['user_full_folder'] = PRIVMSGS_INBOX; + } + + // Now make sure the folder is not used for rules + // We assign another folder id (the one the messages got moved to) or assign the INBOX (to not have to remove any rule) + $sql = 'UPDATE ' . PRIVMSGS_RULES_TABLE . ' SET rule_folder_id = '; + $sql .= ($remove_action == 1) ? $move_to : PRIVMSGS_INBOX; + $sql .= ' WHERE rule_folder_id = ' . $remove_folder_id; + + $db->sql_query($sql); + + $meta_info = append_sid('ucp', "i=pm&mode=$mode"); + $message = $user->lang['FOLDER_REMOVED']; + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'REMOVE_FOLDER', build_hidden_fields($s_hidden_fields)); + } + } + + // Add Rule + if (request::is_set_post('add_rule')) + { + if (check_form_key('ucp_pm_options')) + { + $check_option = request_var('check_option', 0); + $rule_option = request_var('rule_option', 0); + $cond_option = request_var('cond_option', ''); + $action_option = explode('|', request_var('action_option', '')); + $rule_string = ($cond_option != 'none') ? utf8_normalize_nfc(request_var('rule_string', '', true)) : ''; + $rule_user_id = ($cond_option != 'none') ? request_var('rule_user_id', 0) : 0; + $rule_group_id = ($cond_option != 'none') ? request_var('rule_group_id', 0) : 0; + + $action = (int) $action_option[0]; + $folder_id = (int) $action_option[1]; + + if (!$action || !$check_option || !$rule_option || !$cond_option || ($cond_option != 'none' && !$rule_string)) + { + trigger_error('RULE_NOT_DEFINED'); + } + + if (($cond_option == 'user' && !$rule_user_id) || ($cond_option == 'group' && !$rule_group_id)) + { + trigger_error('RULE_NOT_DEFINED'); + } + + $rule_ary = array( + 'user_id' => $user->data['user_id'], + 'rule_check' => $check_option, + 'rule_connection' => $rule_option, + 'rule_string' => $rule_string, + 'rule_user_id' => $rule_user_id, + 'rule_group_id' => $rule_group_id, + 'rule_action' => $action, + 'rule_folder_id' => $folder_id + ); + + $sql = 'SELECT rule_id + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE ' . $db->sql_build_array('SELECT', $rule_ary); + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if ($row) + { + trigger_error('RULE_ALREADY_DEFINED'); + } + + $sql = 'INSERT INTO ' . PRIVMSGS_RULES_TABLE . ' ' . $db->sql_build_array('INSERT', $rule_ary); + $db->sql_query($sql); + + // Update users message rules + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_message_rules = 1 + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $msg = $user->lang['RULE_ADDED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $redirect_url . '">', '</a>'); + meta_refresh(3, $redirect_url); + trigger_error($message); + } + + // Remove Rule + if (request::is_set_post('delete_rule') && !request::is_set_post('cancel')) + { + $delete_id = array_keys(request_var('delete_rule', array(0 => 0))); + $delete_id = (!empty($delete_id[0])) ? $delete_id[0] : 0; + + if (!$delete_id) + { + redirect(append_sid('ucp', 'i=pm&mode=' . $mode)); + } + + // Do we need to confirm? + if (confirm_box(true)) + { + $sql = 'DELETE FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . " + AND rule_id = $delete_id"; + $db->sql_query($sql); + + $meta_info = append_sid('ucp', 'i=pm&mode=' . $mode); + $message = $user->lang['RULE_DELETED']; + + // Reset user_message_rules if no more assigned + $sql = 'SELECT rule_id + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + // Update users message rules + if (!$row) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_message_rules = 0 + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + + meta_refresh(3, $meta_info); + $message .= '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + else + { + confirm_box(false, 'DELETE_RULE', build_hidden_fields(array('delete_rule' => array($delete_id => 1)))); + } + } + + $folder = array(); + + $sql = 'SELECT COUNT(msg_id) as num_messages + FROM ' . PRIVMSGS_TO_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND folder_id = ' . PRIVMSGS_INBOX; + $result = $db->sql_query($sql); + $num_messages = (int) $db->sql_fetchfield('num_messages'); + $db->sql_freeresult($result); + + $folder[PRIVMSGS_INBOX] = array( + 'folder_name' => $user->lang['PM_INBOX'], + 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $num_messages, $user->data['message_limit']) + ); + + $sql = 'SELECT folder_id, folder_name, pm_count + FROM ' . PRIVMSGS_FOLDER_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + $num_user_folder = 0; + while ($row = $db->sql_fetchrow($result)) + { + $num_user_folder++; + $folder[$row['folder_id']] = array( + 'folder_name' => $row['folder_name'], + 'message_status' => sprintf($user->lang['FOLDER_MESSAGE_STATUS'], $row['pm_count'], $user->data['message_limit']) + ); + } + $db->sql_freeresult($result); + + $s_full_folder_options = $s_to_folder_options = $s_folder_options = ''; + + if ($user->data['user_full_folder'] == FULL_FOLDER_NONE) + { + // -3 here to let the correct folder id be selected + $to_folder_id = $config['full_folder_action'] - 3; + } + else + { + $to_folder_id = $user->data['user_full_folder']; + } + + foreach ($folder as $folder_id => $folder_ary) + { + $s_full_folder_options .= '<option value="' . $folder_id . '"' . (($user->data['user_full_folder'] == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + $s_to_folder_options .= '<option value="' . $folder_id . '"' . (($to_folder_id == $folder_id) ? ' selected="selected"' : '') . '>' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + + if ($folder_id != PRIVMSGS_INBOX) + { + $s_folder_options .= '<option value="' . $folder_id . '">' . $folder_ary['folder_name'] . ' (' . $folder_ary['message_status'] . ')</option>'; + } + } + + $s_delete_checked = ($user->data['user_full_folder'] == FULL_FOLDER_DELETE) ? ' checked="checked"' : ''; + $s_hold_checked = ($user->data['user_full_folder'] == FULL_FOLDER_HOLD) ? ' checked="checked"' : ''; + $s_move_checked = ($user->data['user_full_folder'] >= 0) ? ' checked="checked"' : ''; + + if ($user->data['user_full_folder'] == FULL_FOLDER_NONE) + { + switch ($config['full_folder_action']) + { + case 1: + $s_delete_checked = ' checked="checked"'; + break; + + case 2: + $s_hold_checked = ' checked="checked"'; + break; + } + } + + $template->assign_vars(array( + 'S_FULL_FOLDER_OPTIONS' => $s_full_folder_options, + 'S_TO_FOLDER_OPTIONS' => $s_to_folder_options, + 'S_FOLDER_OPTIONS' => $s_folder_options, + 'S_DELETE_CHECKED' => $s_delete_checked, + 'S_HOLD_CHECKED' => $s_hold_checked, + 'S_MOVE_CHECKED' => $s_move_checked, + 'S_MAX_FOLDER_REACHED' => ($num_user_folder >= $config['pm_max_boxes']) ? true : false, + 'S_MAX_FOLDER_ZERO' => ($config['pm_max_boxes'] == 0) ? true : false, + + 'DEFAULT_ACTION' => ($config['full_folder_action'] == 1) ? $user->lang['DELETE_OLDEST_MESSAGES'] : $user->lang['HOLD_NEW_MESSAGES'], + + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=ucp&field=rule_string&select_single=true'), + )); + + $rule_lang = $action_lang = $check_lang = array(); + + // Build all three language arrays + preg_replace('#^((RULE|ACTION|CHECK)_([A-Z0-9_]+))$#e', "\${strtolower('\\2') . '_lang'}[constant('\\1')] = \$user->lang['PM_\\2']['\\3']", array_keys(get_defined_constants())); + + /* + Rule Ordering: + -> CHECK_* -> RULE_* [IN $global_privmsgs_rules:CHECK_*] -> [IF $rule_conditions[RULE_*] [|text|bool|user|group|own_group]] -> ACTION_* + */ + + $check_option = request_var('check_option', 0); + $rule_option = request_var('rule_option', 0); + $cond_option = request_var('cond_option', ''); + $action_option = request_var('action_option', ''); + $back = request_var('back', array('' => 0)); + + if (sizeof($back)) + { + if ($action_option) + { + $action_option = ''; + } + else if ($cond_option) + { + $cond_option = ''; + } + else if ($rule_option) + { + $rule_option = 0; + } + else if ($check_option) + { + $check_option = 0; + } + } + + if (isset($back['action']) && $cond_option == 'none') + { + $back['cond'] = true; + } + + // Check + if (!isset($global_privmsgs_rules[$check_option])) + { + $check_option = 0; + } + + define_check_option(($check_option && !isset($back['rule'])) ? true : false, $check_option, $check_lang); + + if ($check_option && !isset($back['rule'])) + { + define_rule_option(($rule_option && !isset($back['cond'])) ? true : false, $rule_option, $rule_lang, $global_privmsgs_rules[$check_option]); + } + + if ($rule_option && !isset($back['cond'])) + { + if (!isset($global_rule_conditions[$rule_option])) + { + $cond_option = 'none'; + $template->assign_var('NONE_CONDITION', true); + } + else + { + define_cond_option(($cond_option && !isset($back['action'])) ? true : false, $cond_option, $rule_option, $global_rule_conditions); + } + } + + if ($cond_option && !isset($back['action'])) + { + define_action_option(false, $action_option, $action_lang, $folder); + } + + show_defined_rules($user->data['user_id'], $check_lang, $rule_lang, $action_lang, $folder); +} + +/** +* Defining check option for message rules +*/ +function define_check_option($hardcoded, $check_option, $check_lang) +{ + global $template; + + $s_check_options = ''; + if (!$hardcoded) + { + foreach ($check_lang as $value => $lang) + { + $s_check_options .= '<option value="' . $value . '"' . (($value == $check_option) ? ' selected="selected"' : '') . '>' . $lang . '</option>'; + } + } + + $template->assign_vars(array( + 'S_CHECK_DEFINED' => true, + 'S_CHECK_SELECT' => ($hardcoded) ? false : true, + 'CHECK_CURRENT' => isset($check_lang[$check_option]) ? $check_lang[$check_option] : '', + 'S_CHECK_OPTIONS' => $s_check_options, + 'CHECK_OPTION' => $check_option) + ); +} + +/** +* Defining action option for message rules +*/ +function define_action_option($hardcoded, $action_option, $action_lang, $folder) +{ + global $db, $template, $user; + + $l_action = $s_action_options = ''; + if ($hardcoded) + { + $option = explode('|', $action_option); + $action = (int) $option[0]; + $folder_id = (int) $option[1]; + + $l_action = $action_lang[$action]; + if ($action == ACTION_PLACE_INTO_FOLDER) + { + $l_action .= ' -> ' . $folder[$folder_id]['folder_name']; + } + } + else + { + foreach ($action_lang as $action => $lang) + { + if ($action == ACTION_PLACE_INTO_FOLDER) + { + foreach ($folder as $folder_id => $folder_ary) + { + $s_action_options .= '<option value="' . $action . '|' . $folder_id . '"' . (($action_option == $action . '|' . $folder_id) ? ' selected="selected"' : '') . '>' . $lang . ' -> ' . $folder_ary['folder_name'] . '</option>'; + } + } + else + { + $s_action_options .= '<option value="' . $action . '|0"' . (($action_option == $action . '|0') ? ' selected="selected"' : '') . '>' . $lang . '</option>'; + } + } + } + + $template->assign_vars(array( + 'S_ACTION_DEFINED' => true, + 'S_ACTION_SELECT' => ($hardcoded) ? false : true, + 'ACTION_CURRENT' => $l_action, + 'S_ACTION_OPTIONS' => $s_action_options, + 'ACTION_OPTION' => $action_option) + ); +} + +/** +* Defining rule option for message rules +*/ +function define_rule_option($hardcoded, $rule_option, $rule_lang, $check_ary) +{ + global $template; + + $s_rule_options = ''; + if (!$hardcoded) + { + foreach ($check_ary as $value => $_check) + { + $s_rule_options .= '<option value="' . $value . '"' . (($value == $rule_option) ? ' selected="selected"' : '') . '>' . $rule_lang[$value] . '</option>'; + } + } + + $template->assign_vars(array( + 'S_RULE_DEFINED' => true, + 'S_RULE_SELECT' => !$hardcoded, + 'RULE_CURRENT' => isset($rule_lang[$rule_option]) ? $rule_lang[$rule_option] : '', + 'S_RULE_OPTIONS' => $s_rule_options, + 'RULE_OPTION' => $rule_option) + ); +} + +/** +* Defining condition option for message rules +*/ +function define_cond_option($hardcoded, $cond_option, $rule_option, $global_rule_conditions) +{ + global $db, $template, $auth, $user; + + $template->assign_vars(array( + 'S_COND_DEFINED' => true, + 'S_COND_SELECT' => (!$hardcoded && isset($global_rule_conditions[$rule_option])) ? true : false) + ); + + // Define COND_OPTION + if (!isset($global_rule_conditions[$rule_option])) + { + $template->assign_vars(array( + 'COND_OPTION' => 'none', + 'COND_CURRENT' => false) + ); + return; + } + + // Define Condition + $condition = $global_rule_conditions[$rule_option]; + $current_value = ''; + + switch ($condition) + { + case 'text': + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + $template->assign_vars(array( + 'S_TEXT_CONDITION' => true, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => 0, + 'CURRENT_GROUP_ID' => 0) + ); + + $current_value = $rule_string; + break; + + case 'user': + $rule_user_id = request_var('rule_user_id', 0); + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + if ($rule_string && !$rule_user_id) + { + $sql = 'SELECT user_id + FROM ' . USERS_TABLE . " + WHERE username_clean = '" . $db->sql_escape(utf8_clean_string($rule_string)) . "'"; + $result = $db->sql_query($sql); + $rule_user_id = (int) $db->sql_fetchfield('user_id'); + $db->sql_freeresult($result); + + if (!$rule_user_id) + { + $rule_string = ''; + } + } + else if (!$rule_string && $rule_user_id) + { + $sql = 'SELECT username + FROM ' . USERS_TABLE . " + WHERE user_id = $rule_user_id"; + $result = $db->sql_query($sql); + $rule_string = $db->sql_fetchfield('username'); + $db->sql_freeresult($result); + + if (!$rule_string) + { + $rule_user_id = 0; + } + } + + $template->assign_vars(array( + 'S_USER_CONDITION' => true, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => $rule_user_id, + 'CURRENT_GROUP_ID' => 0) + ); + + $current_value = $rule_string; + break; + + case 'group': + $rule_group_id = request_var('rule_group_id', 0); + $rule_string = utf8_normalize_nfc(request_var('rule_string', '', true)); + + $sql = 'SELECT g.group_id, g.group_name, g.group_type + FROM ' . GROUPS_TABLE . ' g '; + + if (!$auth->acl_gets('a_group', 'a_groupadd', 'a_groupdel')) + { + $sql .= 'LEFT JOIN ' . USER_GROUP_TABLE . ' ug + ON ( + g.group_id = ug.group_id + AND ug.user_id = ' . $user->data['user_id'] . ' + AND ug.user_pending = 0 + ) + WHERE (ug.user_id = ' . $user->data['user_id'] . ' OR g.group_type <> ' . GROUP_HIDDEN . ') + AND'; + } + else + { + $sql .= 'WHERE'; + } + + $sql .= " (g.group_name NOT IN ('GUESTS', 'BOTS') OR g.group_type <> " . GROUP_SPECIAL . ') + ORDER BY g.group_type DESC, g.group_name ASC'; + + $result = $db->sql_query($sql); + + $s_group_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + if ($rule_group_id && ($row['group_id'] == $rule_group_id)) + { + $rule_string = (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']); + } + + $s_class = ($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : ''; + $s_selected = ($row['group_id'] == $rule_group_id) ? ' selected="selected"' : ''; + + $s_group_options .= '<option value="' . $row['group_id'] . '"' . $s_class . $s_selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_GROUP_CONDITION' => true, + 'S_GROUP_OPTIONS' => $s_group_options, + 'CURRENT_STRING' => $rule_string, + 'CURRENT_USER_ID' => 0, + 'CURRENT_GROUP_ID' => $rule_group_id) + ); + + $current_value = $rule_string; + break; + + default: + return; + } + + $template->assign_vars(array( + 'COND_OPTION' => $condition, + 'COND_CURRENT' => $current_value) + ); +} + +/** +* Display defined message rules +*/ +function show_defined_rules($user_id, $check_lang, $rule_lang, $action_lang, $folder) +{ + global $db, $template; + + $sql = 'SELECT * + FROM ' . PRIVMSGS_RULES_TABLE . ' + WHERE user_id = ' . $user_id . ' + ORDER BY rule_id ASC'; + $result = $db->sql_query($sql); + + $count = 0; + while ($row = $db->sql_fetchrow($result)) + { + $template->assign_block_vars('rule', array( + 'COUNT' => ++$count, + 'RULE_ID' => $row['rule_id'], + 'CHECK' => $check_lang[$row['rule_check']], + 'RULE' => $rule_lang[$row['rule_connection']], + 'STRING' => $row['rule_string'], + 'ACTION' => $action_lang[$row['rule_action']], + 'FOLDER' => ($row['rule_action'] == ACTION_PLACE_INTO_FOLDER) ? $folder[$row['rule_folder_id']]['folder_name'] : '') + ); + } + $db->sql_freeresult($result); +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_pm_viewfolder.php b/phpBB/modules/ucp/ucp_pm_viewfolder.php new file mode 100644 index 0000000000..36750d69c4 --- /dev/null +++ b/phpBB/modules/ucp/ucp_pm_viewfolder.php @@ -0,0 +1,569 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View message folder +* Called from ucp_pm with mode == 'view' && action == 'view_folder' +*/ +function view_folder($id, $mode, $folder_id, $folder) +{ + global $user, $template, $auth, $db, $cache, $config; + + $submit_export = request::is_set_post('submit_export'); + + $folder_info = get_pm_from($folder_id, $folder, $user->data['user_id']); + + if (!$submit_export) + { + $user->add_lang('viewforum'); + + // Grab icons + $icons = cache::obtain_icons(); + + $color_rows = array('marked', 'replied'); + + // only show the friend/foe color rows if the module is enabled + $zebra_enabled = false; + + $_module = new p_master(); + $_module->list_modules('ucp'); + $_module->set_active('zebra'); + + $zebra_enabled = ($_module->active_module === false) ? false : true; + + unset($_module); + + if ($zebra_enabled) + { + $color_rows = array_merge($color_rows, array('friend', 'foe')); + } + + foreach ($color_rows as $var) + { + $template->assign_block_vars('pm_colour_info', array( + 'IMG' => $user->img("pm_{$var}", ''), + 'CLASS' => "pm_{$var}_colour", + 'LANG' => $user->lang[strtoupper($var) . '_MESSAGE']) + ); + } + + $mark_options = array('mark_important', 'delete_marked'); + + $s_mark_options = ''; + foreach ($mark_options as $mark_option) + { + $s_mark_options .= '<option value="' . $mark_option . '">' . $user->lang[strtoupper($mark_option)] . '</option>'; + } + + // We do the folder moving options here too, for template authors to use... + $s_folder_move_options = ''; + if ($folder_id != PRIVMSGS_NO_BOX && $folder_id != PRIVMSGS_OUTBOX) + { + foreach ($folder as $f_id => $folder_ary) + { + if ($f_id == PRIVMSGS_OUTBOX || $f_id == PRIVMSGS_SENTBOX || $f_id == $folder_id) + { + continue; + } + + $s_folder_move_options .= '<option' . (($f_id != PRIVMSGS_INBOX) ? ' class="sep"' : '') . ' value="' . $f_id . '">'; + $s_folder_move_options .= sprintf($user->lang['MOVE_MARKED_TO_FOLDER'], $folder_ary['folder_name']); + $s_folder_move_options .= (($folder_ary['unread_messages']) ? ' [' . $folder_ary['unread_messages'] . '] ' : '') . '</option>'; + } + } + $friend = $foe = array(); + + // Get friends and foes + $sql = 'SELECT * + FROM ' . ZEBRA_TABLE . ' + WHERE user_id = ' . $user->data['user_id']; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $friend[$row['zebra_id']] = $row['friend']; + $foe[$row['zebra_id']] = $row['foe']; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'S_MARK_OPTIONS' => $s_mark_options, + 'S_MOVE_MARKED_OPTIONS' => $s_folder_move_options) + ); + + // Okay, lets dump out the page ... + if (sizeof($folder_info['pm_list'])) + { + $address_list = array(); + + // Build Recipient List if in outbox/sentbox - max two additional queries + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + $recipient_list = $address = array(); + + foreach ($folder_info['rowset'] as $message_id => $row) + { + $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address'])); + $_save = array('u', 'g'); + foreach ($_save as $save) + { + if (isset($address[$message_id][$save]) && sizeof($address[$message_id][$save])) + { + foreach (array_keys($address[$message_id][$save]) as $ug_id) + { + $recipient_list[$save][$ug_id] = array('name' => $user->lang['NA'], 'colour' => ''); + } + } + } + } + + $_types = array('u', 'g'); + foreach ($_types as $ug_type) + { + if (!empty($recipient_list[$ug_type])) + { + if ($ug_type == 'u') + { + $sql = 'SELECT user_id as id, username as name, user_colour as colour + FROM ' . USERS_TABLE . ' + WHERE '; + } + else + { + $sql = 'SELECT group_id as id, group_name as name, group_colour as colour, group_type + FROM ' . GROUPS_TABLE . ' + WHERE '; + } + $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($recipient_list[$ug_type]))); + + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + if ($ug_type == 'g') + { + $row['name'] = ($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['name']] : $row['name']; + } + + $recipient_list[$ug_type][$row['id']] = array('name' => $row['name'], 'colour' => $row['colour']); + } + $db->sql_freeresult($result); + } + } + + foreach ($address as $message_id => $adr_ary) + { + foreach ($adr_ary as $type => $id_ary) + { + foreach ($id_ary as $ug_id => $_id) + { + if ($type == 'u') + { + $address_list[$message_id][] = get_username_string('full', $ug_id, $recipient_list[$type][$ug_id]['name'], $recipient_list[$type][$ug_id]['colour']); + } + else + { + $user_colour = ($recipient_list[$type][$ug_id]['colour']) ? ' style="font-weight: bold; color:#' . $recipient_list[$type][$ug_id]['colour'] . '"' : ''; + $link = '<a href="' . append_sid('memberlist', 'mode=group&g=' . $ug_id) . '"' . $user_colour . '>'; + $address_list[$message_id][] = $link . $recipient_list[$type][$ug_id]['name'] . (($link) ? '</a>' : ''); + } + } + } + } + unset($recipient_list, $address); + } + + $data = array(); + + foreach ($folder_info['pm_list'] as $message_id) + { + $row = &$folder_info['rowset'][$message_id]; + + $folder_img = ($row['pm_unread']) ? 'pm_unread' : 'pm_read'; + $folder_alt = ($row['pm_unread']) ? 'NEW_MESSAGES' : 'NO_NEW_MESSAGES'; + + // Generate all URIs ... + $view_message_url = append_sid('ucp', "i=$id&mode=view&f=$folder_id&p=$message_id"); + $remove_message_url = append_sid('ucp', "i=$id&mode=compose&action=delete&p=$message_id"); + + $row_indicator = ''; + foreach ($color_rows as $var) + { + if (($var != 'friend' && $var != 'foe' && $row['pm_' . $var]) + || + (($var == 'friend' || $var == 'foe') && isset(${$var}[$row['author_id']]) && ${$var}[$row['author_id']])) + { + $row_indicator = $var; + break; + } + } + + // Send vars to template + $template->assign_block_vars('messagerow', array( + 'PM_CLASS' => ($row_indicator) ? 'pm_' . $row_indicator . '_colour' : '', + + 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'MESSAGE_AUTHOR' => get_username_string('username', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + 'U_MESSAGE_AUTHOR' => get_username_string('profile', $row['author_id'], $row['username'], $row['user_colour'], $row['username']), + + 'FOLDER_ID' => $folder_id, + 'MESSAGE_ID' => $message_id, + 'SENT_TIME' => $user->format_date($row['message_time']), + 'SUBJECT' => censor_text($row['message_subject']), + 'FOLDER' => (isset($folder[$row['folder_id']])) ? $folder[$row['folder_id']]['folder_name'] : '', + 'U_FOLDER' => (isset($folder[$row['folder_id']])) ? append_sid('ucp', 'folder=' . $row['folder_id']) : '', + 'PM_ICON_IMG' => (!empty($icons[$row['icon_id']])) ? '<img src="' . $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] . '" width="' . $icons[$row['icon_id']]['width'] . '" height="' . $icons[$row['icon_id']]['height'] . '" alt="" title="" />' : '', + 'PM_ICON_URL' => (!empty($icons[$row['icon_id']])) ? $config['icons_path'] . '/' . $icons[$row['icon_id']]['img'] : '', + 'FOLDER_IMG' => $user->img($folder_img, $folder_alt), + 'FOLDER_IMG_SRC' => $user->img($folder_img, $folder_alt, 'src'), + 'PM_IMG' => ($row_indicator) ? $user->img('pm_' . $row_indicator, '') : '', + 'ATTACH_ICON_IMG' => ($auth->acl_get('u_pm_download') && $row['message_attachment'] && $config['allow_pm_attach']) ? $user->img('icon_topic_attach', $user->lang['TOTAL_ATTACHMENTS']) : '', + + 'S_PM_DELETED' => ($row['pm_deleted']) ? true : false, + 'S_AUTHOR_DELETED' => ($row['author_id'] == ANONYMOUS) ? true : false, + + 'U_VIEW_PM' => ($row['pm_deleted']) ? '' : $view_message_url, + 'U_REMOVE_PM' => ($row['pm_deleted']) ? $remove_message_url : '', + 'RECIPIENTS' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? implode(', ', $address_list[$message_id]) : '') + ); + } + unset($folder_info['rowset']); + + $template->assign_vars(array( + 'S_SHOW_RECIPIENTS' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? true : false, + 'S_SHOW_COLOUR_LEGEND' => true, + + 'S_PM_ICONS' => ($config['enable_pm_icons']) ? true : false) + ); + } + } + else + { + $export_type = request_var('export_option', ''); + $enclosure = request_var('enclosure', ''); + $delimiter = request_var('delimiter', ''); + + if ($export_type == 'CSV' && ($delimiter === '' || $enclosure === '')) + { + $template->assign_var('PROMPT', true); + } + else + { + // Build Recipient List if in outbox/sentbox + $address = array(); + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + foreach ($folder_info['rowset'] as $message_id => $row) + { + $address[$message_id] = rebuild_header(array('to' => $row['to_address'], 'bcc' => $row['bcc_address'])); + } + } + + foreach ($folder_info['pm_list'] as $message_id) + { + $row = &$folder_info['rowset'][$message_id]; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + + $sql = 'SELECT p.message_text, p.bbcode_uid + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . ' u + WHERE t.user_id = ' . $user->data['user_id'] . " + AND p.author_id = u.user_id + AND t.folder_id = $folder_id + AND t.msg_id = p.msg_id + AND p.msg_id = $message_id"; + $result = $db->sql_query_limit($sql, 1); + $message_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $_types = array('u', 'g'); + foreach ($_types as $ug_type) + { + if (isset($address[$message_id][$ug_type]) && sizeof($address[$message_id][$ug_type])) + { + if ($ug_type == 'u') + { + $sql = 'SELECT user_id as id, username as name + FROM ' . USERS_TABLE . ' + WHERE '; + } + else + { + $sql = 'SELECT group_id as id, group_name as name + FROM ' . GROUPS_TABLE . ' + WHERE '; + } + $sql .= $db->sql_in_set(($ug_type == 'u') ? 'user_id' : 'group_id', array_map('intval', array_keys($address[$message_id][$ug_type]))); + + $result = $db->sql_query($sql); + + while ($info_row = $db->sql_fetchrow($result)) + { + $address[$message_id][$ug_type][$address[$message_id][$ug_type][$info_row['id']]][] = $info_row['name']; + unset($address[$message_id][$ug_type][$info_row['id']]); + } + $db->sql_freeresult($result); + } + } + + decode_message($message_row['message_text'], $message_row['bbcode_uid']); + + $data[] = array( + 'subject' => censor_text($row['message_subject']), + 'sender' => $row['username'], + 'date' => $user->format_date($row['message_time']), + 'to' => ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) ? $address[$message_id] : '', + 'message' => $message_row['message_text'] + ); + } + + switch ($export_type) + { + case 'CSV': + case 'CSV_EXCEL': + $mimetype = 'text/csv'; + $filetype = 'csv'; + + if ($export_type == 'CSV_EXCEL') + { + $enclosure = '"'; + $delimiter = ','; + $newline = "\r\n"; + } + else + { + $newline = "\n"; + } + + $string = ''; + foreach ($data as $value) + { + $recipients = $value['to']; + $value['to'] = $value['bcc'] = ''; + + if (is_array($recipients)) + { + foreach ($recipients as $values) + { + $value['bcc'] .= (isset($values['bcc']) && is_array($values['bcc'])) ? ',' . implode(',', $values['bcc']) : ''; + $value['to'] .= (isset($values['to']) && is_array($values['to'])) ? ',' . implode(',', $values['to']) : ''; + } + + // Remove the commas which will appear before the first entry. + $value['to'] = substr($value['to'], 1); + $value['bcc'] = substr($value['bcc'], 1); + } + + foreach ($value as $tag => $text) + { + $cell = str_replace($enclosure, $enclosure . $enclosure, $text); + + if (strpos($cell, $enclosure) !== false || strpos($cell, $delimiter) !== false || strpos($cell, $newline) !== false) + { + $string .= $enclosure . $text . $enclosure . $delimiter; + } + else + { + $string .= $cell . $delimiter; + } + } + $string = substr($string, 0, -1) . $newline; + } + break; + + case 'XML': + $mimetype = 'application/xml'; + $filetype = 'xml'; + $string = '<?xml version="1.0"?>' . "\n"; + $string .= "<phpbb>\n"; + + foreach ($data as $value) + { + $string .= "\t<privmsg>\n"; + + if (is_array($value['to'])) + { + foreach ($value['to'] as $key => $values) + { + foreach ($values as $type => $types) + { + foreach ($types as $name) + { + $string .= "\t\t<recipient type=\"$type\" status=\"$key\">$name</recipient>\n"; + } + } + } + } + + unset($value['to']); + + foreach ($value as $tag => $text) + { + $string .= "\t\t<$tag>$text</$tag>\n"; + } + + $string .= "\t</privmsg>\n"; + } + $string .= '</phpbb>'; + break; + } + + header('Pragma: no-cache'); + header("Content-Type: $mimetype; name=\"data.$filetype\""); + header("Content-disposition: attachment; filename=data.$filetype"); + echo $string; + exit; + } + } +} + +/** +* Get Messages from folder/user +*/ +function get_pm_from($folder_id, $folder, $user_id) +{ + global $user, $db, $template, $config, $auth; + + $start = request_var('start', 0); + + // Additional vars later, pm ordering is mostly different from post ordering. :/ + $sort_days = request_var('st', 0); + $sort_key = request_var('sk', 't'); + $sort_dir = request_var('sd', 'd'); + + // PM ordering options + $limit_days = array(0 => $user->lang['ALL_MESSAGES'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + // No sort by Author for sentbox/outbox (already only author available) + // Also, sort by msg_id for the time - private messages are not as prone to errors as posts are. + if ($folder_id == PRIVMSGS_OUTBOX || $folder_id == PRIVMSGS_SENTBOX) + { + $sort_by_text = array('t' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql = array('t' => 'p.msg_id', 's' => 'p.message_subject'); + } + else + { + $sort_by_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_sql = array('a' => 'u.username_clean', 't' => 'p.msg_id', 's' => 'p.message_subject'); + } + + $s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = ''; + gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param); + + $folder_sql = 't.folder_id = ' . (int) $folder_id; + + // Limit pms to certain time frame, obtain correct pm count + if ($sort_days) + { + $min_post_time = time() - ($sort_days * 86400); + + if (request::is_set_post('sort')) + { + $start = 0; + } + + $sql = 'SELECT COUNT(t.msg_id) AS pm_count + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . " p + WHERE $folder_sql + AND t.user_id = $user_id + AND t.msg_id = p.msg_id + AND p.message_time >= $min_post_time"; + $result = $db->sql_query_limit($sql, 1); + $pm_count = (int) $db->sql_fetchfield('pm_count'); + $db->sql_freeresult($result); + + $sql_limit_time = "AND p.message_time >= $min_post_time"; + } + else + { + $pm_count = (!empty($folder[$folder_id]['num_messages'])) ? $folder[$folder_id]['num_messages'] : 0; + $sql_limit_time = ''; + } + + $template->assign_vars(array( + 'PAGINATION' => generate_pagination(append_sid('ucp', "i=pm&mode=view&action=view_folder&f=$folder_id&$u_sort_param"), $pm_count, $config['topics_per_page'], $start), + 'PAGE_NUMBER' => on_page($pm_count, $config['topics_per_page'], $start), + 'TOTAL_MESSAGES' => (($pm_count == 1) ? $user->lang['VIEW_PM_MESSAGE'] : sprintf($user->lang['VIEW_PM_MESSAGES'], $pm_count)), + + 'POST_IMG' => (!$auth->acl_get('u_sendpm')) ? $user->img('button_topic_locked', 'PM_LOCKED') : $user->img('button_pm_new', 'POST_PM'), + + 'L_NO_MESSAGES' => (!$auth->acl_get('u_sendpm')) ? $user->lang['POST_PM_LOCKED'] : $user->lang['NO_MESSAGES'], + + 'S_SELECT_SORT_DIR' => $s_sort_dir, + 'S_SELECT_SORT_KEY' => $s_sort_key, + 'S_SELECT_SORT_DAYS' => $s_limit_days, + 'S_TOPIC_ICONS' => ($config['enable_pm_icons']) ? true : false, + + 'U_POST_NEW_TOPIC' => ($auth->acl_get('u_sendpm')) ? append_sid('ucp', 'i=pm&mode=compose') : '', + 'S_PM_ACTION' => append_sid('ucp', "i=pm&mode=view&action=view_folder&f=$folder_id" . (($start !== 0) ? "&start=$start" : ''))) + ); + + // Grab all pm data + $rowset = $pm_list = array(); + + // If the user is trying to reach late pages, start searching from the end + $store_reverse = false; + $sql_limit = $config['topics_per_page']; + if ($start > $pm_count / 2) + { + $store_reverse = true; + + if ($start + $config['topics_per_page'] > $pm_count) + { + $sql_limit = min($config['topics_per_page'], max(1, $pm_count - $start)); + } + + // Select the sort order + $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'ASC' : 'DESC'); + $sql_start = max(0, $pm_count - $sql_limit - $start); + } + else + { + // Select the sort order + $sql_sort_order = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC'); + $sql_start = $start; + } + + $sql = 'SELECT t.*, p.root_level, p.message_time, p.message_subject, p.icon_id, p.to_address, p.message_attachment, p.bcc_address, u.username, u.username_clean, u.user_colour + FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u + WHERE t.user_id = $user_id + AND p.author_id = u.user_id + AND $folder_sql + AND t.msg_id = p.msg_id + $sql_limit_time + ORDER BY $sql_sort_order"; + $result = $db->sql_query_limit($sql, $sql_limit, $sql_start); + + while ($row = $db->sql_fetchrow($result)) + { + $rowset[$row['msg_id']] = $row; + $pm_list[] = $row['msg_id']; + } + $db->sql_freeresult($result); + + $pm_list = ($store_reverse) ? array_reverse($pm_list) : $pm_list; + + return array( + 'pm_count' => $pm_count, + 'pm_list' => $pm_list, + 'rowset' => $rowset + ); +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_pm_viewmessage.php b/phpBB/modules/ucp/ucp_pm_viewmessage.php new file mode 100644 index 0000000000..8b249ab66a --- /dev/null +++ b/phpBB/modules/ucp/ucp_pm_viewmessage.php @@ -0,0 +1,308 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* View private message +*/ +function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) +{ + global $user, $template, $auth, $db, $cache, $config; + + $user->add_lang(array('viewtopic', 'memberlist')); + + $msg_id = (int) $msg_id; + $folder_id = (int) $folder_id; + $author_id = (int) $message_row['author_id']; + + // Not able to view message, it was deleted by the sender + if ($message_row['pm_deleted']) + { + $meta_info = append_sid('ucp', "i=pm&folder=$folder_id"); + $message = $user->lang['NO_AUTH_READ_REMOVED_MESSAGE']; + + $message .= '<br /><br />' . sprintf($user->lang['RETURN_FOLDER'], '<a href="' . $meta_info . '">', '</a>'); + trigger_error($message); + } + + // Do not allow hold messages to be seen + if ($folder_id == PRIVMSGS_HOLD_BOX) + { + trigger_error('NO_AUTH_READ_HOLD_MESSAGE'); + } + + // Grab icons + $icons = cache::obtain_icons(); + + $bbcode = false; + + // Instantiate BBCode if need be + if ($message_row['bbcode_bitfield']) + { + include(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode($message_row['bbcode_bitfield']); + } + + // Assign TO/BCC Addresses to template + write_pm_addresses(array('to' => $message_row['to_address'], 'bcc' => $message_row['bcc_address']), $author_id); + + $user_info = get_user_information($author_id, $message_row); + + // Parse the message and subject + $message = censor_text($message_row['message_text']); + + // Second parse bbcode here + if ($message_row['bbcode_bitfield']) + { + $bbcode->bbcode_second_pass($message, $message_row['bbcode_uid'], $message_row['bbcode_bitfield']); + } + + // Always process smilies after parsing bbcodes + $message = bbcode_nl2br($message); + $message = smiley_text($message); + + // Replace naughty words such as farty pants + $message_row['message_subject'] = censor_text($message_row['message_subject']); + + // Editing information + if ($message_row['message_edit_count'] && $config['display_last_edited']) + { + $l_edit_time_total = ($message_row['message_edit_count'] == 1) ? $user->lang['EDITED_TIME_TOTAL'] : $user->lang['EDITED_TIMES_TOTAL']; + $l_edited_by = '<br /><br />' . sprintf($l_edit_time_total, (!$message_row['message_edit_user']) ? $message_row['username'] : $message_row['message_edit_user'], $user->format_date($message_row['message_edit_time'], false, true), $message_row['message_edit_count']); + } + else + { + $l_edited_by = ''; + } + + // Pull attachment data + $display_notice = false; + $attachments = array(); + + if ($message_row['message_attachment'] && $config['allow_pm_attach']) + { + if ($auth->acl_get('u_pm_download')) + { + $sql = 'SELECT * + FROM ' . ATTACHMENTS_TABLE . " + WHERE post_msg_id = $msg_id + AND in_message = 1 + ORDER BY filetime DESC, post_msg_id ASC"; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $attachments[] = $row; + } + $db->sql_freeresult($result); + + // No attachments exist, but message table thinks they do so go ahead and reset attach flags + if (!sizeof($attachments)) + { + $sql = 'UPDATE ' . PRIVMSGS_TABLE . " + SET message_attachment = 0 + WHERE msg_id = $msg_id"; + $db->sql_query($sql); + } + } + else + { + $display_notice = true; + } + } + + // Assign inline attachments + if (!empty($attachments)) + { + $update_count = array(); + parse_attachments(false, $message, $attachments, $update_count); + + // Update the attachment download counts + if (sizeof($update_count)) + { + $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' + SET download_count = download_count + 1 + WHERE ' . $db->sql_in_set('attach_id', array_unique($update_count)); + $db->sql_query($sql); + } + } + + $user_info['sig'] = ''; + + $signature = ($message_row['enable_sig'] && $config['allow_sig'] && $auth->acl_get('u_sig') && $user->optionget('viewsigs')) ? $user_info['user_sig'] : ''; + + // End signature parsing, only if needed + if ($signature) + { + $signature = censor_text($signature); + + if ($user_info['user_sig_bbcode_bitfield']) + { + if ($bbcode === false) + { + include(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); + $bbcode = new bbcode($user_info['user_sig_bbcode_bitfield']); + } + + $bbcode->bbcode_second_pass($signature, $user_info['user_sig_bbcode_uid'], $user_info['user_sig_bbcode_bitfield']); + } + + $signature = bbcode_nl2br($signature); + $signature = smiley_text($signature); + } + + $url = append_sid('ucp', 'i=pm'); + + $template->assign_vars(array( + 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $user_info['username'], $user_info['user_colour'], $user_info['username']), + + 'RANK_TITLE' => $user_info['rank_title'], + 'RANK_IMG' => $user_info['rank_image'], + 'AUTHOR_AVATAR' => (isset($user_info['avatar'])) ? $user_info['avatar'] : '', + 'AUTHOR_JOINED' => $user->format_date($user_info['user_regdate']), + 'AUTHOR_POSTS' => (!empty($user_info['user_posts'])) ? $user_info['user_posts'] : '', + 'AUTHOR_FROM' => (!empty($user_info['user_from'])) ? $user_info['user_from'] : '', + + 'ONLINE_IMG' => (!$config['load_onlinetrack']) ? '' : ((isset($user_info['online']) && $user_info['online']) ? $user->img('icon_user_online', $user->lang['ONLINE']) : $user->img('icon_user_offline', $user->lang['OFFLINE'])), + 'S_ONLINE' => (!$config['load_onlinetrack']) ? false : ((isset($user_info['online']) && $user_info['online']) ? true : false), + 'DELETE_IMG' => $user->img('icon_post_delete', $user->lang['DELETE_MESSAGE']), + 'INFO_IMG' => $user->img('icon_post_info', $user->lang['VIEW_PM_INFO']), + 'PROFILE_IMG' => $user->img('icon_user_profile', $user->lang['READ_PROFILE']), + 'EMAIL_IMG' => $user->img('icon_contact_email', $user->lang['SEND_EMAIL']), + 'QUOTE_IMG' => $user->img('icon_post_quote', $user->lang['POST_QUOTE_PM']), + 'REPLY_IMG' => $user->img('button_pm_reply', $user->lang['POST_REPLY_PM']), + 'EDIT_IMG' => $user->img('icon_post_edit', $user->lang['POST_EDIT_PM']), + 'MINI_POST_IMG' => $user->img('icon_post_target', $user->lang['PM']), + + 'SENT_DATE' => $user->format_date($message_row['message_time']), + 'SUBJECT' => $message_row['message_subject'], + 'MESSAGE' => $message, + 'SIGNATURE' => ($message_row['enable_sig']) ? $signature : '', + 'EDITED_MESSAGE' => $l_edited_by, + 'MESSAGE_ID' => $message_row['msg_id'], + + 'U_PM' => ($config['allow_privmsg'] && $auth->acl_get('u_sendpm') && ($user_info['user_allow_pm'] || $auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))) ? append_sid('ucp', 'i=pm&mode=compose&u=' . $author_id) : '', + 'U_WWW' => (!empty($user_info['user_website'])) ? $user_info['user_website'] : '', + 'U_ICQ' => ($user_info['user_icq']) ? 'http://www.icq.com/people/webmsg.php?to=' . urlencode($user_info['user_icq']) : '', + 'U_AIM' => ($user_info['user_aim'] && $auth->acl_get('u_sendim')) ? append_sid('memberlist', 'mode=contact&action=aim&u=' . $author_id) : '', + 'U_YIM' => ($user_info['user_yim']) ? 'http://edit.yahoo.com/config/send_webmesg?.target=' . urlencode($user_info['user_yim']) . '&.src=pg' : '', + 'U_MSN' => ($user_info['user_msnm'] && $auth->acl_get('u_sendim')) ? append_sid('memberlist', 'mode=contact&action=msnm&u=' . $author_id) : '', + 'U_JABBER' => ($user_info['user_jabber'] && $auth->acl_get('u_sendim')) ? append_sid('memberlist', 'mode=contact&action=jabber&u=' . $author_id) : '', + + 'U_DELETE' => ($auth->acl_get('u_pm_delete')) ? "$url&mode=compose&action=delete&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_EMAIL' => $user_info['email'], + 'U_QUOTE' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=quote&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_EDIT' => (($message_row['message_time'] > time() - ($config['pm_edit_time'] * 60) || !$config['pm_edit_time']) && $folder_id == PRIVMSGS_OUTBOX && $auth->acl_get('u_pm_edit')) ? "$url&mode=compose&action=edit&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_POST_REPLY_PM' => ($auth->acl_get('u_sendpm') && $author_id != ANONYMOUS) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $message_row['msg_id'] : '', + 'U_PREVIOUS_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=previous", + 'U_NEXT_PM' => "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=next", + + 'S_HAS_ATTACHMENTS' => (sizeof($attachments)) ? true : false, + 'S_DISPLAY_NOTICE' => $display_notice && $message_row['message_attachment'], + 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, + 'S_SPECIAL_FOLDER' => in_array($folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)), + + 'U_PRINT_PM' => ($config['print_pm'] && $auth->acl_get('u_pm_printpm')) ? "$url&f=$folder_id&p=" . $message_row['msg_id'] . "&view=print" : '', + 'U_FORWARD_PM' => ($config['forward_pm'] && $auth->acl_get('u_sendpm') && $auth->acl_get('u_pm_forward')) ? "$url&mode=compose&action=forward&f=$folder_id&p=" . $message_row['msg_id'] : '') + ); + + // Display not already displayed Attachments for this post, we already parsed them. ;) + if (isset($attachments) && sizeof($attachments)) + { + foreach ($attachments as $attachment) + { + $template->assign_block_vars('attachment', array( + 'DISPLAY_ATTACHMENT' => $attachment) + ); + } + } + + if (request_var('view', '') != 'print') + { + // Message History + if (message_history($msg_id, $user->data['user_id'], $message_row, $folder)) + { + $template->assign_var('S_DISPLAY_HISTORY', true); + } + } +} + +/** +* Get user information (only for message display) +*/ +function get_user_information($user_id, $user_row) +{ + global $db, $auth, $user, $cache, $config; + + if (!$user_id) + { + return array(); + } + + if (empty($user_row)) + { + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . (int) $user_id; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + } + + // Some standard values + $user_row['online'] = false; + $user_row['rank_title'] = $user_row['rank_image'] = $user_row['rank_image_src'] = $user_row['email'] = ''; + + // Generate online information for user + if ($config['load_onlinetrack']) + { + $sql = 'SELECT session_user_id, MAX(session_time) as online_time, MIN(session_viewonline) AS viewonline + FROM ' . SESSIONS_TABLE . " + WHERE session_user_id = $user_id + GROUP BY session_user_id"; + $result = $db->sql_query_limit($sql, 1); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + $update_time = $config['load_online_time'] * 60; + if ($row) + { + $user_row['online'] = (time() - $update_time < $row['online_time'] && ($row['viewonline'])) ? true : false; + } + } + + if (!function_exists('get_user_avatar')) + { + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + } + + $user_row['avatar'] = ($user->optionget('viewavatars')) ? get_user_avatar($user_row['user_avatar'], $user_row['user_avatar_type'], $user_row['user_avatar_width'], $user_row['user_avatar_height']) : ''; + + get_user_rank($user_id, $user_row['user_rank'], $user_row['user_posts'], $user_row['rank_title'], $user_row['rank_image'], $user_row['rank_image_src']); + + if (!empty($user_row['user_allow_viewemail']) || $auth->acl_get('a_email')) + { + $user_row['email'] = ($config['board_email_form'] && $config['email_enable']) ? append_sid('memberlist', "mode=email&u=$user_id") : ((($config['board_hide_emails'] && !$auth->acl_get('a_email')) || empty($user_row['user_email'])) ? '' : 'mailto:' . $user_row['user_email']); + } + + return $user_row; +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_prefs.php b/phpBB/modules/ucp/ucp_prefs.php new file mode 100644 index 0000000000..f33ae39ba5 --- /dev/null +++ b/phpBB/modules/ucp/ucp_prefs.php @@ -0,0 +1,357 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_prefs +* Changing user preferences +* @package ucp +*/ +class ucp_prefs +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + $submit = request::is_set_post('submit'); + $error = $data = array(); + $s_hidden_fields = ''; + + switch ($mode) + { + case 'personal': + add_form_key('ucp_prefs_personal'); + $data = array( + 'notifymethod' => request_var('notifymethod', $user->data['user_notify_type']), + 'dateformat' => request_var('dateformat', $user->data['user_dateformat'], true), + 'lang' => basename(request_var('lang', $user->data['user_lang'])), + 'style' => request_var('style', (int) $user->data['user_style']), + 'tz' => request_var('tz', (float) $user->data['user_timezone']), + + 'dst' => request_var('dst', (bool) $user->data['user_dst']), + 'viewemail' => request_var('viewemail', (bool) $user->data['user_allow_viewemail']), + 'massemail' => request_var('massemail', (bool) $user->data['user_allow_massemail']), + 'hideonline' => request_var('hideonline', (bool) !$user->data['user_allow_viewonline']), + 'notifypm' => request_var('notifypm', (bool) $user->data['user_notify_pm']), + 'popuppm' => request_var('popuppm', (bool) $user->optionget('popuppm')), + 'allowpm' => request_var('allowpm', (bool) $user->data['user_allow_pm']), + ); + + if ($data['notifymethod'] == NOTIFY_IM && (!$config['jab_enable'] || !$user->data['user_jabber'] || !@extension_loaded('xml'))) + { + // Jabber isnt enabled, or no jabber field filled in. Update the users table to be sure its correct. + $data['notifymethod'] = NOTIFY_BOTH; + } + + if ($submit) + { + $data['style'] = ($config['override_user_style']) ? $config['default_style'] : $data['style']; + + $error = validate_data($data, array( + 'dateformat' => array('string', false, 1, 30), + 'lang' => array('match', false, '#^[a-z0-9_\-]{2,}$#i'), + 'tz' => array('num', false, -14, 14), + )); + + if (!check_form_key('ucp_prefs_personal')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $user->optionset('popuppm', $data['popuppm']); + + $sql_ary = array( + 'user_allow_pm' => $data['allowpm'], + 'user_allow_viewemail' => $data['viewemail'], + 'user_allow_massemail' => $data['massemail'], + 'user_allow_viewonline' => ($auth->acl_get('u_hideonline')) ? !$data['hideonline'] : $user->data['user_allow_viewonline'], + 'user_notify_type' => $data['notifymethod'], + 'user_notify_pm' => $data['notifypm'], + 'user_options' => $user->data['user_options'], + + 'user_dst' => $data['dst'], + 'user_dateformat' => $data['dateformat'], + 'user_lang' => $data['lang'], + 'user_timezone' => $data['tz'], + 'user_style' => $data['style'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PREFERENCES_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $dateformat_options = ''; + + foreach ($user->lang['dateformats'] as $format => $null) + { + $dateformat_options .= '<option value="' . $format . '"' . (($format == $data['dateformat']) ? ' selected="selected"' : '') . '>'; + $dateformat_options .= $user->format_date(time(), $format, false) . ((strpos($format, '|') !== false) ? $user->lang['VARIANT_DATE_SEPARATOR'] . $user->format_date(time(), $format, true) : ''); + $dateformat_options .= '</option>'; + } + + $s_custom = false; + + $dateformat_options .= '<option value="custom"'; + if (!isset($user->lang['dateformats'][$data['dateformat']])) + { + $dateformat_options .= ' selected="selected"'; + $s_custom = true; + } + $dateformat_options .= '>' . $user->lang['CUSTOM_DATEFORMAT'] . '</option>'; + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'S_NOTIFY_EMAIL' => ($data['notifymethod'] == NOTIFY_EMAIL) ? true : false, + 'S_NOTIFY_IM' => ($data['notifymethod'] == NOTIFY_IM) ? true : false, + 'S_NOTIFY_BOTH' => ($data['notifymethod'] == NOTIFY_BOTH) ? true : false, + 'S_VIEW_EMAIL' => $data['viewemail'], + 'S_MASS_EMAIL' => $data['massemail'], + 'S_ALLOW_PM' => $data['allowpm'], + 'S_HIDE_ONLINE' => $data['hideonline'], + 'S_NOTIFY_PM' => $data['notifypm'], + 'S_POPUP_PM' => $data['popuppm'], + 'S_DST' => $data['dst'], + + 'DATE_FORMAT' => $data['dateformat'], + 'A_DATE_FORMAT' => addslashes($data['dateformat']), + 'S_DATEFORMAT_OPTIONS' => $dateformat_options, + 'S_CUSTOM_DATEFORMAT' => $s_custom, + 'DEFAULT_DATEFORMAT' => $config['default_dateformat'], + 'A_DEFAULT_DATEFORMAT' => addslashes($config['default_dateformat']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_STYLE_OPTIONS' => ($config['override_user_style']) ? '' : style_select($data['style']), + 'S_TZ_OPTIONS' => tz_select($data['tz'], true), + 'S_CAN_HIDE_ONLINE' => ($auth->acl_get('u_hideonline')) ? true : false, + 'S_SELECT_NOTIFY' => ($config['jab_enable'] && $user->data['user_jabber'] && @extension_loaded('xml')) ? true : false) + ); + + break; + + case 'view': + + add_form_key('ucp_prefs_view'); + + $data = array( + 'topic_sk' => request_var('topic_sk', (!empty($user->data['user_topic_sortby_type'])) ? $user->data['user_topic_sortby_type'] : 't'), + 'topic_sd' => request_var('topic_sd', (!empty($user->data['user_topic_sortby_dir'])) ? $user->data['user_topic_sortby_dir'] : 'd'), + 'topic_st' => request_var('topic_st', (!empty($user->data['user_topic_show_days'])) ? $user->data['user_topic_show_days'] : 0), + + 'post_sk' => request_var('post_sk', (!empty($user->data['user_post_sortby_type'])) ? $user->data['user_post_sortby_type'] : 't'), + 'post_sd' => request_var('post_sd', (!empty($user->data['user_post_sortby_dir'])) ? $user->data['user_post_sortby_dir'] : 'a'), + 'post_st' => request_var('post_st', (!empty($user->data['user_post_show_days'])) ? $user->data['user_post_show_days'] : 0), + + 'images' => request_var('images', (bool) $user->optionget('viewimg')), + 'flash' => request_var('flash', (bool) $user->optionget('viewflash')), + 'smilies' => request_var('smilies', (bool) $user->optionget('viewsmilies')), + 'sigs' => request_var('sigs', (bool) $user->optionget('viewsigs')), + 'avatars' => request_var('avatars', (bool) $user->optionget('viewavatars')), + 'wordcensor' => request_var('wordcensor', (bool) $user->optionget('viewcensors')), + ); + + if ($submit) + { + $error = validate_data($data, array( + 'topic_sk' => array('string', false, 1, 1), + 'topic_sd' => array('string', false, 1, 1), + 'post_sk' => array('string', false, 1, 1), + 'post_sd' => array('string', false, 1, 1), + )); + + if (!check_form_key('ucp_prefs_view')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $user->optionset('viewimg', $data['images']); + $user->optionset('viewflash', $data['flash']); + $user->optionset('viewsmilies', $data['smilies']); + $user->optionset('viewsigs', $data['sigs']); + $user->optionset('viewavatars', $data['avatars']); + + if ($auth->acl_get('u_chgcensors')) + { + $user->optionset('viewcensors', $data['wordcensor']); + } + + $sql_ary = array( + 'user_options' => $user->data['user_options'], + 'user_topic_sortby_type' => $data['topic_sk'], + 'user_post_sortby_type' => $data['post_sk'], + 'user_topic_sortby_dir' => $data['topic_sd'], + 'user_post_sortby_dir' => $data['post_sd'], + + 'user_topic_show_days' => $data['topic_st'], + 'user_post_show_days' => $data['post_st'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + meta_refresh(3, $this->u_action); + $message = $user->lang['PREFERENCES_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']); + + // Topic ordering options + $limit_topic_days = array(0 => $user->lang['ALL_TOPICS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + $sort_by_topic_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']); + $sort_by_topic_sql = array('a' => 't.topic_first_poster_name', 't' => 't.topic_last_post_time', 'r' => 't.topic_replies', 's' => 't.topic_title', 'v' => 't.topic_views'); + + // Post ordering options + $limit_post_days = array(0 => $user->lang['ALL_POSTS'], 1 => $user->lang['1_DAY'], 7 => $user->lang['7_DAYS'], 14 => $user->lang['2_WEEKS'], 30 => $user->lang['1_MONTH'], 90 => $user->lang['3_MONTHS'], 180 => $user->lang['6_MONTHS'], 365 => $user->lang['1_YEAR']); + + $sort_by_post_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']); + $sort_by_post_sql = array('a' => 'u.username_clean', 't' => 'p.post_id', 's' => 'p.post_subject'); + + $_options = array('topic', 'post'); + foreach ($_options as $sort_option) + { + ${'s_limit_' . $sort_option . '_days'} = '<select name="' . $sort_option . '_st">'; + foreach (${'limit_' . $sort_option . '_days'} as $day => $text) + { + $selected = ($data[$sort_option . '_st'] == $day) ? ' selected="selected"' : ''; + ${'s_limit_' . $sort_option . '_days'} .= '<option value="' . $day . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_limit_' . $sort_option . '_days'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_key'} = '<select name="' . $sort_option . '_sk">'; + foreach (${'sort_by_' . $sort_option . '_text'} as $key => $text) + { + $selected = ($data[$sort_option . '_sk'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_key'} .= '<option value="' . $key . '"' . $selected . '>' . $text . '</option>'; + } + ${'s_sort_' . $sort_option . '_key'} .= '</select>'; + + ${'s_sort_' . $sort_option . '_dir'} = '<select name="' . $sort_option . '_sd">'; + foreach ($sort_dir_text as $key => $value) + { + $selected = ($data[$sort_option . '_sd'] == $key) ? ' selected="selected"' : ''; + ${'s_sort_' . $sort_option . '_dir'} .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>'; + } + ${'s_sort_' . $sort_option . '_dir'} .= '</select>'; + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'S_IMAGES' => $data['images'], + 'S_FLASH' => $data['flash'], + 'S_SMILIES' => $data['smilies'], + 'S_SIGS' => $data['sigs'], + 'S_AVATARS' => $data['avatars'], + 'S_DISABLE_CENSORS' => $data['wordcensor'], + + 'S_CHANGE_CENSORS' => ($auth->acl_get('u_chgcensors')) ? true : false, + + 'S_TOPIC_SORT_DAYS' => $s_limit_topic_days, + 'S_TOPIC_SORT_KEY' => $s_sort_topic_key, + 'S_TOPIC_SORT_DIR' => $s_sort_topic_dir, + 'S_POST_SORT_DAYS' => $s_limit_post_days, + 'S_POST_SORT_KEY' => $s_sort_post_key, + 'S_POST_SORT_DIR' => $s_sort_post_dir) + ); + + break; + + case 'post': + + $data = array( + 'bbcode' => request_var('bbcode', $user->optionget('bbcode')), + 'smilies' => request_var('smilies', $user->optionget('smilies')), + 'sig' => request_var('sig', $user->optionget('attachsig')), + 'notify' => request_var('notify', (bool) $user->data['user_notify']), + ); + add_form_key('ucp_prefs_post'); + + if ($submit) + { + if (check_form_key('ucp_prefs_post')) + { + $user->optionset('bbcode', $data['bbcode']); + $user->optionset('smilies', $data['smilies']); + $user->optionset('attachsig', $data['sig']); + + $sql_ary = array( + 'user_options' => $user->data['user_options'], + 'user_notify' => $data['notify'], + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $msg = $user->lang['PREFERENCES_UPDATED']; + } + else + { + $msg = $user->lang['FORM_INVALID']; + } + meta_refresh(3, $this->u_action); + $message = $msg . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'S_BBCODE' => $data['bbcode'], + 'S_SMILIES' => $data['smilies'], + 'S_SIG' => $data['sig'], + 'S_NOTIFY' => $data['notify']) + ); + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PREFS_' . strtoupper($mode)], + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action) + ); + + $this->tpl_name = 'ucp_prefs_' . $mode; + $this->page_title = 'UCP_PREFS_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_profile.php b/phpBB/modules/ucp/ucp_profile.php new file mode 100644 index 0000000000..fc4e7e174b --- /dev/null +++ b/phpBB/modules/ucp/ucp_profile.php @@ -0,0 +1,646 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_profile +* Changing profile settings +* +* @todo what about pertaining user_sig_options? +* @package ucp +*/ +class ucp_profile +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + $user->add_lang('posting'); + + $preview = request::variable('preview', false, false, request::POST); + $submit = request::variable('submit', false, false, request::POST); + $delete = request::variable('delete', false, false, request::POST); + $error = $data = array(); + $s_hidden_fields = ''; + + switch ($mode) + { + case 'reg_details': + + $data = array( + 'username' => utf8_normalize_nfc(request_var('username', $user->data['username'], true)), + 'email' => strtolower(request_var('email', $user->data['user_email'])), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'new_password' => request_var('new_password', '', true), + 'cur_password' => request_var('cur_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + ); + + add_form_key('ucp_reg_details'); + + if ($submit) + { + // Do not check cur_password, it is the old one. + $check_ary = array( + 'new_password' => array( + array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', true, $config['min_pass_chars'], $config['max_pass_chars']), + 'email' => array( + array('string', false, 6, 60), + array('email')), + 'email_confirm' => array('string', true, 6, 60), + ); + + if ($auth->acl_get('u_chgname') && $config['allow_namechange']) + { + $check_ary['username'] = array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username'), + ); + } + + $error = validate_data($data, $check_ary); + + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && $data['password_confirm'] != $data['new_password']) + { + $error[] = 'NEW_PASSWORD_ERROR'; + } + + if (($data['new_password'] || ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) || ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange'])) && !phpbb_check_hash($data['cur_password'], $user->data['user_password'])) + { + $error[] = 'CUR_PASSWORD_ERROR'; + } + + // Only check the new password against the previous password if there have been no errors + if (!sizeof($error) && $auth->acl_get('u_chgpasswd') && $data['new_password'] && phpbb_check_hash($data['new_password'], $user->data['user_password'])) + { + $error[] = 'SAME_PASSWORD_ERROR'; + } + + if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email'] && $data['email_confirm'] != $data['email']) + { + $error[] = 'NEW_EMAIL_ERROR'; + } + + if (!check_form_key('ucp_reg_details')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $sql_ary = array( + 'username' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? $data['username'] : $user->data['username'], + 'username_clean' => ($auth->acl_get('u_chgname') && $config['allow_namechange']) ? utf8_clean_string($data['username']) : $user->data['username_clean'], + 'user_email' => ($auth->acl_get('u_chgemail')) ? $data['email'] : $user->data['user_email'], + 'user_email_hash' => ($auth->acl_get('u_chgemail')) ? hexdec(crc32($data['email']) . strlen($data['email'])) : $user->data['user_email_hash'], + 'user_password' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? phpbb_hash($data['new_password']) : $user->data['user_password'], + 'user_passchg' => ($auth->acl_get('u_chgpasswd') && $data['new_password']) ? time() : 0, + ); + + if ($auth->acl_get('u_chgname') && $config['allow_namechange'] && $data['username'] != $user->data['username']) + { + add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_NAME', $user->data['username'], $data['username']); + } + + if ($auth->acl_get('u_chgpasswd') && $data['new_password'] && !phpbb_check_hash($data['new_password'], $user->data['user_password'])) + { + $user->reset_login_keys(); + add_log('user', $user->data['user_id'], 'LOG_USER_NEW_PASSWORD', $data['username']); + } + + if ($auth->acl_get('u_chgemail') && $data['email'] != $user->data['user_email']) + { + add_log('user', $user->data['user_id'], 'LOG_USER_UPDATE_EMAIL', $data['username'], $user->data['user_email'], $data['email']); + } + + $message = 'PROFILE_UPDATED'; + + if ($config['email_enable'] && $data['email'] != $user->data['user_email'] && $user->data['user_type'] != USER_FOUNDER && ($config['require_activation'] == USER_ACTIVATION_SELF || $config['require_activation'] == USER_ACTIVATION_ADMIN)) + { + $message = ($config['require_activation'] == USER_ACTIVATION_SELF) ? 'ACCOUNT_EMAIL_CHANGED' : 'ACCOUNT_EMAIL_CHANGED_ADMIN'; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $server_url = generate_board_url(); + + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len > 6) ? $key_len : 6; + $user_actkey = substr($user_actkey, 0, $key_len); + + $messenger = new messenger(false); + + $template_file = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? 'user_activate_inactive' : 'user_activate'; + $messenger->template($template_file, $user->data['user_lang']); + + $messenger->to($data['email'], $data['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u={$user->data['user_id']}&k=$user_actkey") + ); + + $messenger->send(NOTIFY_EMAIL); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); + + // Also include founders + $where_sql = ' WHERE user_type = ' . USER_FOUNDER; + + if (sizeof($admin_ary)) + { + $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' ' . + $where_sql; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_USER_DETAILS' => "$server_url/memberlist." . PHP_EXT . "?mode=viewprofile&u={$user->data['user_id']}", + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u={$user->data['user_id']}&k=$user_actkey") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + + user_active_flip('deactivate', $user->data['user_id'], INACTIVE_PROFILE); + + // Because we want the profile to be reactivated we set user_newpasswd to empty (else the reactivation will fail) + $sql_ary['user_actkey'] = $user_actkey; + $sql_ary['user_newpasswd'] = ''; + } + + if (sizeof($sql_ary)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + } + + // Need to update config, forum, topic, posting, messages, etc. + if ($data['username'] != $user->data['username'] && $auth->acl_get('u_chgname') && $config['allow_namechange']) + { + user_update_name($user->data['username'], $data['username']); + } + + // Now, we can remove the user completely (kill the session) - NOT BEFORE!!! + if (!empty($sql_ary['user_actkey'])) + { + meta_refresh(5, append_sid('index')); + $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid('index') . '">', '</a>'); + + // Because the user gets deactivated we log him out too, killing his session + $user->session_kill(); + } + else + { + meta_refresh(3, $this->u_action); + $message = $user->lang[$message] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + } + + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'USERNAME' => $data['username'], + 'EMAIL' => $data['email'], + 'PASSWORD_CONFIRM' => $data['password_confirm'], + 'NEW_PASSWORD' => $data['new_password'], + 'CUR_PASSWORD' => '', + + 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_CHANGE_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + + 'S_FORCE_PASSWORD' => ($auth->acl_get('u_chgpasswd') && $config['chg_passforce'] && $user->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400)) ? true : false, + 'S_CHANGE_USERNAME' => ($config['allow_namechange'] && $auth->acl_get('u_chgname')) ? true : false, + 'S_CHANGE_EMAIL' => ($auth->acl_get('u_chgemail')) ? true : false, + 'S_CHANGE_PASSWORD' => ($auth->acl_get('u_chgpasswd')) ? true : false) + ); + break; + + case 'profile_info': + + include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); + + $cp = new custom_profile(); + + $cp_data = $cp_error = array(); + + $data = array( + 'icq' => request_var('icq', $user->data['user_icq']), + 'aim' => request_var('aim', $user->data['user_aim']), + 'msn' => request_var('msn', $user->data['user_msnm']), + 'yim' => request_var('yim', $user->data['user_yim']), + 'jabber' => utf8_normalize_nfc(request_var('jabber', $user->data['user_jabber'], true)), + 'website' => request_var('website', $user->data['user_website']), + 'location' => utf8_normalize_nfc(request_var('location', $user->data['user_from'], true)), + 'occupation' => utf8_normalize_nfc(request_var('occupation', $user->data['user_occ'], true)), + 'interests' => utf8_normalize_nfc(request_var('interests', $user->data['user_interests'], true)), + ); + + if ($config['allow_birthdays']) + { + $data['bday_day'] = $data['bday_month'] = $data['bday_year'] = 0; + + if ($user->data['user_birthday']) + { + list($data['bday_day'], $data['bday_month'], $data['bday_year']) = explode('-', $user->data['user_birthday']); + } + + $data['bday_day'] = request_var('bday_day', $data['bday_day']); + $data['bday_month'] = request_var('bday_month', $data['bday_month']); + $data['bday_year'] = request_var('bday_year', $data['bday_year']); + $data['user_birthday'] = sprintf('%2d-%2d-%4d', $data['bday_day'], $data['bday_month'], $data['bday_year']); + } + + add_form_key('ucp_profile_info'); + + if ($submit) + { + $validate_array = array( + 'icq' => array( + array('string', true, 3, 15), + array('match', true, '#^[0-9]+$#i')), + 'aim' => array('string', true, 3, 255), + 'msn' => array('string', true, 5, 255), + 'jabber' => array( + array('string', true, 5, 255), + array('jabber')), + 'yim' => array('string', true, 5, 255), + 'website' => array( + array('string', true, 12, 255), + array('match', true, '#^http[s]?://(.*?\.)*?[a-z0-9\-]+\.[a-z]{2,4}#i')), + 'location' => array('string', true, 2, 100), + 'occupation' => array('string', true, 2, 500), + 'interests' => array('string', true, 2, 500), + ); + + if ($config['allow_birthdays']) + { + $validate_array = array_merge($validate_array, array( + 'bday_day' => array('num', true, 1, 31), + 'bday_month' => array('num', true, 1, 12), + 'bday_year' => array('num', true, 1901, gmdate('Y', time()) + 50), + 'user_birthday' => array('date', true), + )); + } + + $error = validate_data($data, $validate_array); + + // validate custom profile fields + $cp->submit_cp_field('profile', $user->get_iso_lang_id(), $cp_data, $cp_error); + + if (sizeof($cp_error)) + { + $error = array_merge($error, $cp_error); + } + + if (!check_form_key('ucp_profile_info')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error)) + { + $data['notify'] = $user->data['user_notify_type']; + + if (!$config['jab_enable'] || !$data['jabber'] || !@extension_loaded('xml')) + { + // User has not filled in a jabber address (Or one of the modules is disabled or jabber is disabled) + // Disable notify by Jabber now for this user. + $data['notify'] = NOTIFY_BOTH; + } + + $sql_ary = array( + 'user_icq' => $data['icq'], + 'user_aim' => $data['aim'], + 'user_msnm' => $data['msn'], + 'user_yim' => $data['yim'], + 'user_jabber' => $data['jabber'], + 'user_website' => $data['website'], + 'user_from' => $data['location'], + 'user_occ' => $data['occupation'], + 'user_interests'=> $data['interests'], + 'user_notify_type' => $data['notify'], + ); + + if ($config['allow_birthdays']) + { + $sql_ary['user_birthday'] = $data['user_birthday']; + } + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + // Update Custom Fields + if (sizeof($cp_data)) + { + $sql = 'UPDATE ' . PROFILE_FIELDS_DATA_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $cp_data) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + if (!$db->sql_affectedrows()) + { + $cp_data['user_id'] = (int) $user->data['user_id']; + + $db->sql_return_on_error(true); + + $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . $db->sql_build_array('INSERT', $cp_data); + $db->sql_query($sql); + + $db->sql_return_on_error(false); + } + } + + meta_refresh(3, $this->u_action); + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + if ($config['allow_birthdays']) + { + $s_birthday_day_options = '<option value="0"' . ((!$data['bday_day']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 32; $i++) + { + $selected = ($i == $data['bday_day']) ? ' selected="selected"' : ''; + $s_birthday_day_options .= "<option value=\"$i\"$selected>$i</option>"; + } + + $s_birthday_month_options = '<option value="0"' . ((!$data['bday_month']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = 1; $i < 13; $i++) + { + $selected = ($i == $data['bday_month']) ? ' selected="selected"' : ''; + $s_birthday_month_options .= "<option value=\"$i\"$selected>$i</option>"; + } + $s_birthday_year_options = ''; + + $now = getdate(); + $s_birthday_year_options = '<option value="0"' . ((!$data['bday_year']) ? ' selected="selected"' : '') . '>--</option>'; + for ($i = $now['year'] - 100; $i <= $now['year']; $i++) + { + $selected = ($i == $data['bday_year']) ? ' selected="selected"' : ''; + $s_birthday_year_options .= "<option value=\"$i\"$selected>$i</option>"; + } + unset($now); + + $template->assign_vars(array( + 'S_BIRTHDAY_DAY_OPTIONS' => $s_birthday_day_options, + 'S_BIRTHDAY_MONTH_OPTIONS' => $s_birthday_month_options, + 'S_BIRTHDAY_YEAR_OPTIONS' => $s_birthday_year_options, + 'S_BIRTHDAYS_ENABLED' => true, + )); + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + + 'ICQ' => $data['icq'], + 'YIM' => $data['yim'], + 'AIM' => $data['aim'], + 'MSN' => $data['msn'], + 'JABBER' => $data['jabber'], + 'WEBSITE' => $data['website'], + 'LOCATION' => $data['location'], + 'OCCUPATION'=> $data['occupation'], + 'INTERESTS' => $data['interests'], + )); + + // Get additional profile fields and assign them to the template block var 'profile_fields' + $user->get_profile_fields($user->data['user_id']); + + $cp->generate_profile_fields('profile', $user->get_iso_lang_id()); + + break; + + case 'signature': + + if (!$auth->acl_get('u_sig')) + { + trigger_error('NO_AUTH_SIGNATURE'); + } + + include(PHPBB_ROOT_PATH . 'includes/functions_posting.' . PHP_EXT); + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $enable_bbcode = ($config['allow_sig_bbcode']) ? ((request_var('disable_bbcode', !$user->optionget('bbcode'))) ? false : true) : false; + $enable_smilies = ($config['allow_sig_smilies']) ? ((request_var('disable_smilies', !$user->optionget('smilies'))) ? false : true) : false; + $enable_urls = ($config['allow_sig_links']) ? ((request_var('disable_magic_url', false)) ? false : true) : false; + + $signature = utf8_normalize_nfc(request_var('signature', (string) $user->data['user_sig'], true)); + + add_form_key('ucp_sig'); + + if ($submit || $preview) + { + include(PHPBB_ROOT_PATH . 'includes/message_parser.' . PHP_EXT); + + if (!sizeof($error)) + { + $message_parser = new parse_message($signature); + + // Allowing Quote BBCode + $message_parser->parse($enable_bbcode, $enable_urls, $enable_smilies, $config['allow_sig_img'], $config['allow_sig_flash'], true, $config['allow_sig_links'], true, 'sig'); + + if (sizeof($message_parser->warn_msg)) + { + $error[] = implode('<br />', $message_parser->warn_msg); + } + + if (!check_form_key('ucp_sig')) + { + $error[] = 'FORM_INVALID'; + } + + if (!sizeof($error) && $submit) + { + $sql_ary = array( + 'user_sig' => (string) $message_parser->message, + 'user_sig_bbcode_uid' => (string) $message_parser->bbcode_uid, + 'user_sig_bbcode_bitfield' => $message_parser->bbcode_bitfield + ); + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' + WHERE user_id = ' . $user->data['user_id']; + $db->sql_query($sql); + + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + } + + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $signature_preview = ''; + if ($preview) + { + // Now parse it for displaying + $signature_preview = $message_parser->format_display($enable_bbcode, $enable_urls, $enable_smilies, false); + unset($message_parser); + } + + decode_message($signature, $user->data['user_sig_bbcode_uid']); + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'SIGNATURE' => $signature, + 'SIGNATURE_PREVIEW' => $signature_preview, + + 'S_BBCODE_CHECKED' => (!$enable_bbcode) ? ' checked="checked"' : '', + 'S_SMILIES_CHECKED' => (!$enable_smilies) ? ' checked="checked"' : '', + 'S_MAGIC_URL_CHECKED' => (!$enable_urls) ? ' checked="checked"' : '', + + 'BBCODE_STATUS' => ($config['allow_sig_bbcode']) ? sprintf($user->lang['BBCODE_IS_ON'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>') : sprintf($user->lang['BBCODE_IS_OFF'], '<a href="' . append_sid('faq', 'mode=bbcode') . '">', '</a>'), + 'SMILIES_STATUS' => ($config['allow_sig_smilies']) ? $user->lang['SMILIES_ARE_ON'] : $user->lang['SMILIES_ARE_OFF'], + 'IMG_STATUS' => ($config['allow_sig_img']) ? $user->lang['IMAGES_ARE_ON'] : $user->lang['IMAGES_ARE_OFF'], + 'FLASH_STATUS' => ($config['allow_sig_flash']) ? $user->lang['FLASH_IS_ON'] : $user->lang['FLASH_IS_OFF'], + 'URL_STATUS' => ($config['allow_sig_links']) ? $user->lang['URL_IS_ON'] : $user->lang['URL_IS_OFF'], + + 'L_SIGNATURE_EXPLAIN' => sprintf($user->lang['SIGNATURE_EXPLAIN'], $config['max_sig_chars']), + + 'S_BBCODE_ALLOWED' => $config['allow_sig_bbcode'], + 'S_SMILIES_ALLOWED' => $config['allow_sig_smilies'], + 'S_BBCODE_IMG' => ($config['allow_sig_img']) ? true : false, + 'S_BBCODE_FLASH' => ($config['allow_sig_flash']) ? true : false, + 'S_LINKS_ALLOWED' => ($config['allow_sig_links']) ? true : false) + ); + + // Build custom bbcodes array + display_custom_bbcodes(); + + break; + + case 'avatar': + + include(PHPBB_ROOT_PATH . 'includes/functions_display.' . PHP_EXT); + + $display_gallery = request_var('display_gallery', '0'); + $avatar_select = basename(request_var('avatar_select', '')); + $category = basename(request_var('category', '')); + + $can_upload = ($config['allow_avatar_upload'] && file_exists(PHPBB_ROOT_PATH . $config['avatar_path']) && @is_writable(PHPBB_ROOT_PATH . $config['avatar_path']) && $auth->acl_get('u_chgavatar') && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; + + add_form_key('ucp_avatar'); + + if ($submit) + { + if (check_form_key('ucp_avatar')) + { + if (avatar_process_user($error)) + { + meta_refresh(3, $this->u_action); + $message = $user->lang['PROFILE_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + } + else + { + $error[] = 'FORM_INVALID'; + } + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'AVATAR' => get_user_avatar($user->data['user_avatar'], $user->data['user_avatar_type'], $user->data['user_avatar_width'], $user->data['user_avatar_height']), + 'AVATAR_SIZE' => $config['avatar_filesize'], + + 'U_GALLERY' => append_sid('ucp', 'i=profile&mode=avatar&display_gallery=1'), + + 'S_FORM_ENCTYPE' => ($can_upload) ? ' enctype="multipart/form-data"' : '', + + 'L_AVATAR_EXPLAIN' => sprintf($user->lang['AVATAR_EXPLAIN'], $config['avatar_max_width'], $config['avatar_max_height'], $config['avatar_filesize'] / 1024), + )); + + if ($display_gallery && $auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) + { + avatar_gallery($category, $avatar_select, 4); + } + else + { + $avatars_enabled = ($can_upload || ($auth->acl_get('u_chgavatar') && ($config['allow_avatar_local'] || $config['allow_avatar_remote']))) ? true : false; + + $template->assign_vars(array( + 'AVATAR_WIDTH' => request_var('width', $user->data['user_avatar_width']), + 'AVATAR_HEIGHT' => request_var('height', $user->data['user_avatar_height']), + + 'S_AVATARS_ENABLED' => $avatars_enabled, + 'S_UPLOAD_AVATAR_FILE' => $can_upload, + 'S_UPLOAD_AVATAR_URL' => $can_upload, + 'S_LINK_AVATAR' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_remote']) ? true : false, + 'S_DISPLAY_GALLERY' => ($auth->acl_get('u_chgavatar') && $config['allow_avatar_local']) ? true : false) + ); + } + + break; + } + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_PROFILE_' . strtoupper($mode)], + + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action) + ); + + // Set desired template + $this->tpl_name = 'ucp_profile_' . $mode; + $this->page_title = 'UCP_PROFILE_' . strtoupper($mode); + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_register.php b/phpBB/modules/ucp/ucp_register.php new file mode 100644 index 0000000000..a3a128f1b2 --- /dev/null +++ b/phpBB/modules/ucp/ucp_register.php @@ -0,0 +1,490 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_register +* Board registration +* @package ucp +*/ +class ucp_register +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + // + if ($config['require_activation'] == USER_ACTIVATION_DISABLE) + { + trigger_error('UCP_REGISTER_DISABLE'); + } + + include(PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT); + + $coppa = request::is_set('coppa') ? ((request_var('coppa', false)) ? 1 : 0) : false; + $agreed = request::variable('agreed', false, false, request::POST) ? 1 : 0; + $submit = request::is_set_post('submit'); + $change_lang = request_var('change_lang', ''); + $user_lang = request_var('lang', $user->lang_name); + + if ($agreed) + { + add_form_key('ucp_register'); + } + else + { + add_form_key('ucp_register_terms'); + } + + + if ($config['enable_confirm']) + { + include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_factory.' . PHP_EXT); + $captcha = phpbb_captcha_factory::get_instance($config['captcha_plugin']); + $captcha->init(CONFIRM_REG); + } + + if ($change_lang || $user_lang != $config['default_lang']) + { + $use_lang = ($change_lang) ? basename($change_lang) : basename($user_lang); + + if (file_exists($user->lang_path . $use_lang . '/')) + { + if ($change_lang) + { + $submit = false; + + // Setting back agreed to let the user view the agreement in his/her language + $agreed = (request::is_set_post('change_lang')) ? 0 : $agreed; + } + + $user->lang_name = $lang = $use_lang; + $user->lang = array(); + $user->add_lang(array('common', 'ucp')); + } + else + { + $change_lang = ''; + $user_lang = $user->lang_name; + } + } + + $cp = new custom_profile(); + + $error = $cp_data = $cp_error = array(); + + + if (!$agreed || ($coppa === false && $config['coppa_enable']) || ($coppa && !$config['coppa_enable'])) + { + $add_lang = ($change_lang) ? '&change_lang=' . urlencode($change_lang) : ''; + $add_coppa = ($coppa !== false) ? '&coppa=' . $coppa : ''; + + $s_hidden_fields = array(); + + // If we change the language, we want to pass on some more possible parameter. + if ($change_lang) + { + // We do not include the password + $s_hidden_fields = array_merge($s_hidden_fields, array( + 'username' => utf8_normalize_nfc(request_var('username', '', true)), + 'email' => strtolower(request_var('email', '')), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'lang' => $user->lang_name, + 'tz' => request_var('tz', (float) $config['board_timezone']), + )); + + if ($config['enable_confirm']) + { + $s_hidden_fields = array_merge($s_hidden_fields, $captcha->get_hidden_fields()); + } + } + + if ($coppa === false && $config['coppa_enable']) + { + $now = getdate(); + $coppa_birthday = $user->format_date(mktime($now['hours'] + $user->data['user_dst'], $now['minutes'], $now['seconds'], $now['mon'], $now['mday'] - 1, $now['year'] - 13), $user->lang['DATE_FORMAT']); + unset($now); + + $template->assign_vars(array( + 'L_COPPA_NO' => sprintf($user->lang['UCP_COPPA_BEFORE'], $coppa_birthday), + 'L_COPPA_YES' => sprintf($user->lang['UCP_COPPA_ON_AFTER'], $coppa_birthday), + + 'U_COPPA_NO' => append_sid('ucp', 'mode=register&coppa=0' . $add_lang), + 'U_COPPA_YES' => append_sid('ucp', 'mode=register&coppa=1' . $add_lang), + + 'S_SHOW_COPPA' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + 'S_UCP_ACTION' => append_sid('ucp', 'mode=register' . $add_lang), + )); + } + else + { + $template->assign_vars(array( + 'L_TERMS_OF_USE' => sprintf($user->lang['TERMS_OF_USE_CONTENT'], $config['sitename'], generate_board_url()), + + 'S_SHOW_COPPA' => false, + 'S_REGISTRATION' => true, + 'S_HIDDEN_FIELDS' => build_hidden_fields($s_hidden_fields), + 'S_UCP_ACTION' => append_sid('ucp', 'mode=register' . $add_lang . $add_coppa), + ) + ); + } + + $this->tpl_name = 'ucp_agreement'; + return; + } + + + // Try to manually determine the timezone and adjust the dst if the server date/time complies with the default setting +/- 1 + $timezone = date('Z') / 3600; + $is_dst = date('I'); + + if ($config['board_timezone'] == $timezone || $config['board_timezone'] == ($timezone - 1)) + { + $timezone = ($is_dst) ? $timezone - 1 : $timezone; + + if (!isset($user->lang['tz_zones'][(string) $timezone])) + { + $timezone = $config['board_timezone']; + } + } + else + { + $is_dst = $config['board_dst']; + $timezone = $config['board_timezone']; + } + + $data = array( + 'username' => utf8_normalize_nfc(request_var('username', '', true)), + 'new_password' => request_var('new_password', '', true), + 'password_confirm' => request_var('password_confirm', '', true), + 'email' => strtolower(request_var('email', '')), + 'email_confirm' => strtolower(request_var('email_confirm', '')), + 'lang' => basename(request_var('lang', $user->lang_name)), + 'tz' => request_var('tz', (float) $timezone), + ); + + // Check and initialize some variables if needed + if ($submit) + { + $error = validate_data($data, array( + 'username' => array( + array('string', false, $config['min_name_chars'], $config['max_name_chars']), + array('username', '')), + 'new_password' => array( + array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), + array('password')), + 'password_confirm' => array('string', false, $config['min_pass_chars'], $config['max_pass_chars']), + 'email' => array( + array('string', false, 6, 60), + array('email')), + 'email_confirm' => array('string', false, 6, 60), + 'tz' => array('num', false, -14, 14), + 'lang' => array('match', false, '#^[a-z_\-]{2,}$#i'), + )); + if (!check_form_key('ucp_register')) + { + $error[] = $user->lang['FORM_INVALID']; + } + // Replace "error" strings with their real, localised form + $error = preg_replace('#^([A-Z_]+)$#e', "(!empty(\$user->lang['\\1'])) ? \$user->lang['\\1'] : '\\1'", $error); + + if ($config['enable_confirm']) + { + $vc_response = $captcha->validate(); + if ($vc_response) + { + $error[] = $vc_response; + } + else + { + $captcha->reset(); + } + if ($config['max_reg_attempts'] && $captcha->get_attempt_count() > $config['max_reg_attempts']) + { + $error[] = $user->lang['TOO_MANY_REGISTERS']; + } + } + // DNSBL check + if ($config['check_dnsbl']) + { + if (($dnsbl = $user->check_dnsbl('register')) !== false) + { + $error[] = sprintf($user->lang['IP_BLACKLISTED'], $user->ip, $dnsbl[1]); + } + } + + // validate custom profile fields + $cp->submit_cp_field('register', $user->get_iso_lang_id(), $cp_data, $error); + + if (!sizeof($error)) + { + if ($data['new_password'] != $data['password_confirm']) + { + $error[] = $user->lang['NEW_PASSWORD_ERROR']; + } + + if ($data['email'] != $data['email_confirm']) + { + $error[] = $user->lang['NEW_EMAIL_ERROR']; + } + } + + if (!sizeof($error)) + { + $server_url = generate_board_url(); + + // Which group by default? + $group_name = ($coppa) ? 'REGISTERED_COPPA' : 'REGISTERED'; + + $sql = 'SELECT group_id + FROM ' . GROUPS_TABLE . " + WHERE group_name = '" . $db->sql_escape($group_name) . "' + AND group_type = " . GROUP_SPECIAL; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_GROUP'); + } + + $group_id = $row['group_id']; + + if (($coppa || + $config['require_activation'] == USER_ACTIVATION_SELF || + $config['require_activation'] == USER_ACTIVATION_ADMIN) && $config['email_enable']) + { + $user_actkey = gen_rand_string(10); + $key_len = 54 - (strlen($server_url)); + $key_len = ($key_len < 6) ? 6 : $key_len; + $user_actkey = substr($user_actkey, 0, $key_len); + + $user_type = USER_INACTIVE; + $user_inactive_reason = INACTIVE_REGISTER; + $user_inactive_time = time(); + } + else + { + $user_type = USER_NORMAL; + $user_actkey = ''; + $user_inactive_reason = 0; + $user_inactive_time = 0; + } + + $user_row = array( + 'username' => $data['username'], + 'user_password' => phpbb_hash($data['new_password']), + 'user_email' => $data['email'], + 'group_id' => (int) $group_id, + 'user_timezone' => (float) $data['tz'], + 'user_dst' => $is_dst, + 'user_lang' => $data['lang'], + 'user_type' => $user_type, + 'user_actkey' => $user_actkey, + 'user_ip' => $user->ip, + 'user_regdate' => time(), + 'user_inactive_reason' => $user_inactive_reason, + 'user_inactive_time' => $user_inactive_time, + ); + + // Register user... + $user_id = user_add($user_row, $cp_data); + + // This should not happen, because the required variables are listed above... + if ($user_id === false) + { + trigger_error('NO_USER', E_USER_ERROR); + } + + if ($coppa && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_COPPA']; + $email_template = 'coppa_welcome_inactive'; + } + else if ($config['require_activation'] == USER_ACTIVATION_SELF && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_INACTIVE']; + $email_template = 'user_welcome_inactive'; + } + else if ($config['require_activation'] == USER_ACTIVATION_ADMIN && $config['email_enable']) + { + $message = $user->lang['ACCOUNT_INACTIVE_ADMIN']; + $email_template = 'admin_welcome_inactive'; + } + else + { + $message = $user->lang['ACCOUNT_ADDED']; + $email_template = 'user_welcome'; + } + + if ($config['email_enable']) + { + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $messenger = new messenger(false); + + $messenger->template($email_template, $data['lang']); + + $messenger->to($data['email'], $data['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'PASSWORD' => htmlspecialchars_decode($data['new_password']), + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u=$user_id&k=$user_actkey") + ); + + if ($coppa) + { + $messenger->assign_vars(array( + 'FAX_INFO' => $config['coppa_fax'], + 'MAIL_INFO' => $config['coppa_mail'], + 'EMAIL_ADDRESS' => $data['email']) + ); + } + + $messenger->send(NOTIFY_EMAIL); + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + $admin_ary = (!empty($admin_ary[0]['a_user'])) ? $admin_ary[0]['a_user'] : array(); + + // Also include founders + $where_sql = ' WHERE user_type = ' . USER_FOUNDER; + + if (sizeof($admin_ary)) + { + $where_sql .= ' OR ' . $db->sql_in_set('user_id', $admin_ary); + } + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' ' . + $where_sql; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($data['username']), + 'U_USER_DETAILS' => "$server_url/memberlist." . PHP_EXT . "?mode=viewprofile&u=$user_id", + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u=$user_id&k=$user_actkey") + ); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + } + + $message = $message . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid('index') . '">', '</a>'); + trigger_error($message); + } + } + + $s_hidden_fields = array( + 'agreed' => 'true', + 'change_lang' => 0, + ); + + if ($config['coppa_enable']) + { + $s_hidden_fields['coppa'] = $coppa; + } + $s_hidden_fields = build_hidden_fields($s_hidden_fields); + + $confirm_image = ''; + + // Visual Confirmation - Show images + + if ($config['enable_confirm']) + { + if ($change_lang) + { + $str = '&change_lang=' . $change_lang; + } + else + { + $str = ''; + } + + $template->assign_vars(array( + 'L_CONFIRM_EXPLAIN' => sprintf($user->lang['CONFIRM_EXPLAIN'], '<a href="mailto:' . htmlspecialchars($config['board_contact']) . '">', '</a>'), + 'S_CAPTCHA' => $captcha->get_template(), + )); + } + + // + $l_reg_cond = ''; + switch ($config['require_activation']) + { + case USER_ACTIVATION_SELF: + $l_reg_cond = $user->lang['UCP_EMAIL_ACTIVATE']; + break; + + case USER_ACTIVATION_ADMIN: + $l_reg_cond = $user->lang['UCP_ADMIN_ACTIVATE']; + break; + } + + $template->assign_vars(array( + 'ERROR' => (sizeof($error)) ? implode('<br />', $error) : '', + 'USERNAME' => $data['username'], + 'PASSWORD' => $data['new_password'], + 'PASSWORD_CONFIRM' => $data['password_confirm'], + 'EMAIL' => $data['email'], + 'EMAIL_CONFIRM' => $data['email_confirm'], + + 'L_REG_COND' => $l_reg_cond, + 'L_USERNAME_EXPLAIN' => sprintf($user->lang[$config['allow_name_chars'] . '_EXPLAIN'], $config['min_name_chars'], $config['max_name_chars']), + 'L_PASSWORD_EXPLAIN' => sprintf($user->lang[$config['pass_complex'] . '_EXPLAIN'], $config['min_pass_chars'], $config['max_pass_chars']), + + 'S_LANG_OPTIONS' => language_select($data['lang']), + 'S_TZ_OPTIONS' => tz_select($data['tz']), + 'S_COPPA' => $coppa, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => append_sid('ucp', 'mode=register'), + ) + ); + + // + $user->profile_fields = array(); + + // Generate profile fields -> Template Block Variable profile_fields + $cp->generate_profile_fields('register', $user->get_iso_lang_id()); + + // + $this->tpl_name = 'ucp_register'; + $this->page_title = 'UCP_REGISTRATION'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_remind.php b/phpBB/modules/ucp/ucp_remind.php new file mode 100644 index 0000000000..fd8d1cebc6 --- /dev/null +++ b/phpBB/modules/ucp/ucp_remind.php @@ -0,0 +1,124 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_remind +* Sending password reminders +* @package ucp +*/ +class ucp_remind +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $username = request_var('username', '', true); + $email = strtolower(request_var('email', '')); + $submit = request::is_set_post('submit'); + + if ($submit) + { + $sql = 'SELECT user_id, username, user_permissions, user_email, user_jabber, user_notify_type, user_type, user_lang, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_email = '" . $db->sql_escape($email) . "' + AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_EMAIL_USER'); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('NO_USER'); + } + + if ($user_row['user_type'] == USER_INACTIVE) + { + if ($user_row['user_inactive_reason'] == INACTIVE_MANUAL) + { + trigger_error('ACCOUNT_DEACTIVATED'); + } + else + { + trigger_error('ACCOUNT_NOT_ACTIVATED'); + } + } + + // Check users permissions + $auth2 = new auth(); + $auth2->acl($user_row); + + if (!$auth2->acl_get('u_chgpasswd')) + { + trigger_error('NO_AUTH_PASSWORD_REMINDER'); + } + + $server_url = generate_board_url(); + + $key_len = 54 - strlen($server_url); + $key_len = max(6, $key_len); // we want at least 6 + $key_len = ($config['max_pass_chars']) ? min($key_len, $config['max_pass_chars']) : $key_len; // we want at most $config['max_pass_chars'] + $user_actkey = substr(gen_rand_string(10), 0, $key_len); + $user_password = gen_rand_string(8); + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_newpasswd = '" . $db->sql_escape(phpbb_hash($user_password)) . "', user_actkey = '" . $db->sql_escape($user_actkey) . "' + WHERE user_id = " . $user_row['user_id']; + $db->sql_query($sql); + + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + + $messenger = new messenger(false); + + $messenger->template('user_activate_passwd', $user_row['user_lang']); + + $messenger->to($user_row['user_email'], $user_row['username']); + $messenger->im($user_row['user_jabber'], $user_row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'PASSWORD' => htmlspecialchars_decode($user_password), + 'U_ACTIVATE' => "$server_url/ucp." . PHP_EXT . "?mode=activate&u={$user_row['user_id']}&k=$user_actkey") + ); + + $messenger->send($user_row['user_notify_type']); + + meta_refresh(3, append_sid('index')); + + $message = $user->lang['PASSWORD_UPDATED'] . '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid('index') . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'USERNAME' => $username, + 'EMAIL' => $email, + 'S_PROFILE_ACTION' => append_sid('ucp', 'mode=sendpassword'), + )); + + $this->tpl_name = 'ucp_remind'; + $this->page_title = 'UCP_REMIND'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_resend.php b/phpBB/modules/ucp/ucp_resend.php new file mode 100644 index 0000000000..a3b79ffb0f --- /dev/null +++ b/phpBB/modules/ucp/ucp_resend.php @@ -0,0 +1,164 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_resend +* Resending activation emails +* @package ucp +*/ +class ucp_resend +{ + var $u_action; + + function main($id, $mode) + { + global $db, $user, $auth, $template, $config; + + $username = request_var('username', '', true); + $email = strtolower(request_var('email', '')); + $submit = request::is_set_post('submit'); + + add_form_key('ucp_resend'); + + if ($submit) + { + if (!check_form_key('ucp_resend')) + { + trigger_error('FORM_INVALID'); + } + + $sql = 'SELECT user_id, group_id, username, user_email, user_type, user_lang, user_actkey, user_inactive_reason + FROM ' . USERS_TABLE . " + WHERE user_email = '" . $db->sql_escape($email) . "' + AND username_clean = '" . $db->sql_escape(utf8_clean_string($username)) . "'"; + $result = $db->sql_query($sql); + $user_row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$user_row) + { + trigger_error('NO_EMAIL_USER'); + } + + if ($user_row['user_type'] == USER_IGNORE) + { + trigger_error('NO_USER'); + } + + if (!$user_row['user_actkey'] && $user_row['user_type'] != USER_INACTIVE) + { + trigger_error('ACCOUNT_ALREADY_ACTIVATED'); + } + + if (!$user_row['user_actkey'] || ($user_row['user_type'] == USER_INACTIVE && $user_row['user_inactive_reason'] == INACTIVE_MANUAL)) + { + trigger_error('ACCOUNT_DEACTIVATED'); + } + + // Determine coppa status on group (REGISTERED(_COPPA)) + $sql = 'SELECT group_name, group_type + FROM ' . GROUPS_TABLE . ' + WHERE group_id = ' . $user_row['group_id']; + $result = $db->sql_query($sql); + $row = $db->sql_fetchrow($result); + $db->sql_freeresult($result); + + if (!$row) + { + trigger_error('NO_GROUP'); + } + + $coppa = ($row['group_name'] == 'REGISTERED_COPPA' && $row['group_type'] == GROUP_SPECIAL) ? true : false; + + include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); + $messenger = new messenger(false); + + if ($config['require_activation'] == USER_ACTIVATION_SELF || $coppa) + { + $messenger->template(($coppa) ? 'coppa_resend_inactive' : 'user_resend_inactive', $user_row['user_lang']); + $messenger->to($user_row['user_email'], $user_row['username']); + + $messenger->headers('X-AntiAbuse: Board servername - ' . $config['server_name']); + $messenger->headers('X-AntiAbuse: User_id - ' . $user->data['user_id']); + $messenger->headers('X-AntiAbuse: Username - ' . $user->data['username']); + $messenger->headers('X-AntiAbuse: User IP - ' . $user->ip); + + $messenger->assign_vars(array( + 'WELCOME_MSG' => htmlspecialchars_decode(sprintf($user->lang['WELCOME_SUBJECT'], $config['sitename'])), + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_ACTIVATE' => generate_board_url() . '/ucp.' . PHP_EXT . "?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}") + ); + + if ($coppa) + { + $messenger->assign_vars(array( + 'FAX_INFO' => $config['coppa_fax'], + 'MAIL_INFO' => $config['coppa_mail'], + 'EMAIL_ADDRESS' => $user_row['user_email']) + ); + } + + $messenger->send(NOTIFY_EMAIL); + } + + if ($config['require_activation'] == USER_ACTIVATION_ADMIN) + { + // Grab an array of user_id's with a_user permissions ... these users can activate a user + $admin_ary = $auth->acl_get_list(false, 'a_user', false); + + $sql = 'SELECT user_id, username, user_email, user_lang, user_jabber, user_notify_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('user_id', $admin_ary[0]['a_user']); + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $messenger->template('admin_activate', $row['user_lang']); + $messenger->to($row['user_email'], $row['username']); + $messenger->im($row['user_jabber'], $row['username']); + + $messenger->assign_vars(array( + 'USERNAME' => htmlspecialchars_decode($user_row['username']), + 'U_USER_DETAILS' => generate_board_url() . '/memberlist.' . PHP_EXT . "?mode=viewprofile&u={$user_row['user_id']}", + 'U_ACTIVATE' => generate_board_url() . '/ucp.' . PHP_EXT . "?mode=activate&u={$user_row['user_id']}&k={$user_row['user_actkey']}", + )); + + $messenger->send($row['user_notify_type']); + } + $db->sql_freeresult($result); + } + + meta_refresh(3, append_sid('index')); + + $message = ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? $user->lang['ACIVATION_EMAIL_SENT_ADMIN'] : $user->lang['ACTIVATION_EMAIL_SENT']; + $message .= '<br /><br />' . sprintf($user->lang['RETURN_INDEX'], '<a href="' . append_sid('index') . '">', '</a>'); + trigger_error($message); + } + + $template->assign_vars(array( + 'USERNAME' => $username, + 'EMAIL' => $email, + 'S_PROFILE_ACTION' => append_sid('ucp', 'mode=resend_act'), + )); + + $this->tpl_name = 'ucp_resend'; + $this->page_title = 'UCP_RESEND'; + } +} + +?>
\ No newline at end of file diff --git a/phpBB/modules/ucp/ucp_zebra.php b/phpBB/modules/ucp/ucp_zebra.php new file mode 100644 index 0000000000..c45eb9a1d6 --- /dev/null +++ b/phpBB/modules/ucp/ucp_zebra.php @@ -0,0 +1,253 @@ +<?php +/** +* +* @package ucp +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* ucp_zebra +* @package ucp +*/ +class ucp_zebra +{ + var $u_action; + + function main($id, $mode) + { + global $config, $db, $user, $auth, $template; + + $submit = request::is_set_post('submit') || request::is_set('add', request::GET) || request::is_set('remove', request::GET); + $s_hidden_fields = ''; + + $l_mode = strtoupper($mode); + + if ($submit) + { + $data = $error = array(); + $updated = false; + + $var_ary = array( + 'usernames' => array(0), + 'add' => '', + ); + + foreach ($var_ary as $var => $default) + { + $data[$var] = request_var($var, $default, true); + } + + if (!empty($data['add']) || sizeof($data['usernames'])) + { + if (confirm_box(true)) + { + if ($data['add']) + { + $data['add'] = array_map('trim', array_map('utf8_clean_string', explode("\n", $data['add']))); + + // Do these name/s exist on a list already? If so, ignore ... we could be + // 'nice' and automatically handle names added to one list present on + // the other (by removing the existing one) ... but I have a feeling this + // may lead to complaints + $sql = 'SELECT z.*, u.username, u.username_clean + FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u + WHERE z.user_id = ' . $user->data['user_id'] . ' + AND u.user_id = z.zebra_id'; + $result = $db->sql_query($sql); + + $friends = $foes = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['friend']) + { + $friends[] = utf8_clean_string($row['username']); + } + else + { + $foes[] = utf8_clean_string($row['username']); + } + } + $db->sql_freeresult($result); + + // remove friends from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], $friends); + + if (sizeof($data['add']) < $n && $mode == 'foes') + { + $error[] = $user->lang['NOT_ADDED_FOES_FRIENDS']; + } + + // remove foes from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], $foes); + + if (sizeof($data['add']) < $n && $mode == 'friends') + { + $error[] = $user->lang['NOT_ADDED_FRIENDS_FOES']; + } + + // remove the user himself from the username array + $n = sizeof($data['add']); + $data['add'] = array_diff($data['add'], array(utf8_clean_string($user->data['username']))); + + if (sizeof($data['add']) < $n) + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_SELF']; + } + + unset($friends, $foes, $n); + + if (sizeof($data['add'])) + { + $sql = 'SELECT user_id, user_type + FROM ' . USERS_TABLE . ' + WHERE ' . $db->sql_in_set('username_clean', $data['add']) . ' + AND user_type <> ' . USER_INACTIVE; + $result = $db->sql_query($sql); + + $user_id_ary = array(); + while ($row = $db->sql_fetchrow($result)) + { + if ($row['user_id'] != ANONYMOUS && $row['user_type'] != USER_IGNORE) + { + $user_id_ary[] = $row['user_id']; + } + else + { + $error[] = $user->lang['NOT_ADDED_' . $l_mode . '_ANONYMOUS']; + } + } + $db->sql_freeresult($result); + + if (sizeof($user_id_ary)) + { + // Remove users from foe list if they are admins or moderators + if ($mode == 'foes') + { + $perms = array(); + foreach ($auth->acl_get_list($user_id_ary, array('a_', 'm_')) as $forum_id => $forum_ary) + { + foreach ($forum_ary as $auth_option => $user_ary) + { + $perms = array_merge($perms, $user_ary); + } + } + + $perms = array_unique($perms); + + if (sizeof($perms)) + { + $error[] = $user->lang['NOT_ADDED_FOES_MOD_ADMIN']; + } + + // This may not be right ... it may yield true when perms equate to deny + $user_id_ary = array_diff($user_id_ary, $perms); + unset($perms); + } + + if (sizeof($user_id_ary)) + { + $sql_mode = ($mode == 'friends') ? 'friend' : 'foe'; + + $sql_ary = array(); + foreach ($user_id_ary as $zebra_id) + { + $sql_ary[] = array( + 'user_id' => (int) $user->data['user_id'], + 'zebra_id' => (int) $zebra_id, + $sql_mode => 1 + ); + } + + $db->sql_multi_insert(ZEBRA_TABLE, $sql_ary); + + $updated = true; + } + unset($user_id_ary); + } + else if (!sizeof($error)) + { + $error[] = $user->lang['USER_NOT_FOUND_OR_INACTIVE']; + } + } + } + else if (sizeof($data['usernames'])) + { + // Force integer values + $data['usernames'] = array_map('intval', $data['usernames']); + + $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' + WHERE user_id = ' . $user->data['user_id'] . ' + AND ' . $db->sql_in_set('zebra_id', $data['usernames']); + $db->sql_query($sql); + + $updated = true; + } + + if ($updated) + { + meta_refresh(3, $this->u_action); + $message = $user->lang[$l_mode . '_UPDATED'] . '<br />' . implode('<br />', $error) . ((sizeof($error)) ? '<br />' : '') . '<br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>'); + trigger_error($message); + } + else + { + $template->assign_var('ERROR', implode('<br />', $error)); + } + } + else + { + confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array( + 'mode' => $mode, + 'submit' => true, + 'usernames' => $data['usernames'], + 'add' => $data['add'])) + ); + } + } + } + + $sql_and = ($mode == 'friends') ? 'z.friend = 1' : 'z.foe = 1'; + $sql = 'SELECT z.*, u.username, u.username_clean + FROM ' . ZEBRA_TABLE . ' z, ' . USERS_TABLE . ' u + WHERE z.user_id = ' . $user->data['user_id'] . " + AND $sql_and + AND u.user_id = z.zebra_id + ORDER BY u.username_clean ASC"; + $result = $db->sql_query($sql); + + $s_username_options = ''; + while ($row = $db->sql_fetchrow($result)) + { + $s_username_options .= '<option value="' . $row['zebra_id'] . '">' . $row['username'] . '</option>'; + } + $db->sql_freeresult($result); + + $template->assign_vars(array( + 'L_TITLE' => $user->lang['UCP_ZEBRA_' . $l_mode], + + 'U_FIND_USERNAME' => append_sid('memberlist', 'mode=searchuser&form=ucp&field=add'), + + 'S_USERNAME_OPTIONS' => $s_username_options, + 'S_HIDDEN_FIELDS' => $s_hidden_fields, + 'S_UCP_ACTION' => $this->u_action, + )); + + $this->tpl_name = 'ucp_zebra_' . $mode; + $this->page_title = 'UCP_ZEBRA_' . $l_mode; + } +} + +?>
\ No newline at end of file |