Ajout du FR
Ajout du FR + correction du "functions.php"
This commit is contained in:
4
includes/.htaccess
Normal file
4
includes/.htaccess
Normal file
@@ -0,0 +1,4 @@
|
||||
<Files *>
|
||||
Order Allow,Deny
|
||||
Deny from All
|
||||
</Files>
|
||||
1732
includes/acp/acp_attachments.php
Normal file
1732
includes/acp/acp_attachments.php
Normal file
File diff suppressed because it is too large
Load Diff
298
includes/acp/acp_ban.php
Normal file
298
includes/acp/acp_ban.php
Normal file
@@ -0,0 +1,298 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_ban
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $user, $template, $request, $phpbb_dispatcher;
|
||||
global $phpbb_root_path, $phpEx;
|
||||
|
||||
if (!function_exists('user_ban'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
$bansubmit = $request->is_set_post('bansubmit');
|
||||
$unbansubmit = $request->is_set_post('unbansubmit');
|
||||
|
||||
$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 = $request->variable('ban', '', true);
|
||||
$ban_length = $request->variable('banlength', 0);
|
||||
$ban_length_other = $request->variable('banlengthother', '');
|
||||
$ban_exclude = $request->variable('banexclude', 0);
|
||||
$ban_reason = $request->variable('banreason', '', true);
|
||||
$ban_give_reason = $request->variable('bangivereason', '', true);
|
||||
|
||||
if ($ban)
|
||||
{
|
||||
$abort_ban = false;
|
||||
/**
|
||||
* Use this event to modify the ban details before the ban is performed
|
||||
*
|
||||
* @event core.acp_ban_before
|
||||
* @var string mode One of the following: user, ip, email
|
||||
* @var string ban Either string or array with usernames, ips or email addresses
|
||||
* @var int ban_length Ban length in minutes
|
||||
* @var string ban_length_other Ban length as a date (YYYY-MM-DD)
|
||||
* @var bool ban_exclude Are we banning or excluding from another ban
|
||||
* @var string ban_reason Ban reason displayed to moderators
|
||||
* @var string ban_give_reason Ban reason displayed to the banned user
|
||||
* @var mixed abort_ban Either false, or an error message that is displayed to the user.
|
||||
* If a string is given the bans are not issued.
|
||||
* @since 3.1.0-RC5
|
||||
*/
|
||||
$vars = array(
|
||||
'mode',
|
||||
'ban',
|
||||
'ban_length',
|
||||
'ban_length_other',
|
||||
'ban_exclude',
|
||||
'ban_reason',
|
||||
'ban_give_reason',
|
||||
'abort_ban',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_ban_before', compact($vars)));
|
||||
|
||||
if ($abort_ban)
|
||||
{
|
||||
trigger_error($abort_ban . adm_back_link($this->u_action));
|
||||
}
|
||||
user_ban($mode, $ban, $ban_length, $ban_length_other, $ban_exclude, $ban_reason, $ban_give_reason);
|
||||
|
||||
/**
|
||||
* Use this event to perform actions after the ban has been performed
|
||||
*
|
||||
* @event core.acp_ban_after
|
||||
* @var string mode One of the following: user, ip, email
|
||||
* @var string ban Either string or array with usernames, ips or email addresses
|
||||
* @var int ban_length Ban length in minutes
|
||||
* @var string ban_length_other Ban length as a date (YYYY-MM-DD)
|
||||
* @var bool ban_exclude Are we banning or excluding from another ban
|
||||
* @var string ban_reason Ban reason displayed to moderators
|
||||
* @var string ban_give_reason Ban reason displayed to the banned user
|
||||
* @since 3.1.0-RC5
|
||||
*/
|
||||
$vars = array(
|
||||
'mode',
|
||||
'ban',
|
||||
'ban_length',
|
||||
'ban_length_other',
|
||||
'ban_exclude',
|
||||
'ban_reason',
|
||||
'ban_give_reason',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_ban_after', compact($vars)));
|
||||
|
||||
trigger_error($user->lang['BAN_UPDATE_SUCCESSFUL'] . adm_back_link($this->u_action));
|
||||
}
|
||||
}
|
||||
else if ($unbansubmit)
|
||||
{
|
||||
$ban = $request->variable('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("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_ban&field=ban'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display ban options
|
||||
*/
|
||||
static public 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';
|
||||
|
||||
$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';
|
||||
|
||||
$sql = 'SELECT *
|
||||
FROM ' . BANLIST_TABLE . '
|
||||
WHERE (ban_end >= ' . time() . "
|
||||
OR ban_end = 0)
|
||||
AND ban_ip <> ''
|
||||
ORDER BY ban_ip";
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
|
||||
$field = 'ban_email';
|
||||
|
||||
$sql = 'SELECT *
|
||||
FROM ' . BANLIST_TABLE . '
|
||||
WHERE (ban_end >= ' . time() . "
|
||||
OR ban_end = 0)
|
||||
AND ban_email <> ''
|
||||
ORDER BY ban_email";
|
||||
break;
|
||||
}
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$banned_options = $excluded_options = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$option = '<option value="' . $row['ban_id'] . '">' . $row[$field] . '</option>';
|
||||
|
||||
if ($row['ban_exclude'])
|
||||
{
|
||||
$excluded_options[] = $option;
|
||||
}
|
||||
else
|
||||
{
|
||||
$banned_options[] = $option;
|
||||
}
|
||||
|
||||
$time_length = ($row['ban_end']) ? ($row['ban_end'] - $row['ban_start']) / 60 : 0;
|
||||
|
||||
if ($time_length == 0)
|
||||
{
|
||||
// Banned permanently
|
||||
$ban_length = $user->lang['PERMANENT'];
|
||||
}
|
||||
else if (isset($ban_end_text[$time_length]))
|
||||
{
|
||||
// Banned for a given duration
|
||||
$ban_length = $user->lang('BANNED_UNTIL_DURATION', $ban_end_text[$time_length], $user->format_date($row['ban_end'], false, true));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Banned until given date
|
||||
$ban_length = $user->lang('BANNED_UNTIL_DATE', $user->format_date($row['ban_end'], false, true));
|
||||
}
|
||||
|
||||
$template->assign_block_vars('bans', array(
|
||||
'BAN_ID' => (int) $row['ban_id'],
|
||||
'LENGTH' => $ban_length,
|
||||
'A_LENGTH' => addslashes($ban_length),
|
||||
'REASON' => $row['ban_reason'],
|
||||
'A_REASON' => addslashes($row['ban_reason']),
|
||||
'GIVE_REASON' => $row['ban_give_reason'],
|
||||
'A_GIVE_REASON' => addslashes($row['ban_give_reason']),
|
||||
));
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$options = '';
|
||||
if ($excluded_options)
|
||||
{
|
||||
$options .= '<optgroup label="' . $user->lang['OPTIONS_EXCLUDED'] . '">';
|
||||
$options .= implode('', $excluded_options);
|
||||
$options .= '</optgroup>';
|
||||
}
|
||||
|
||||
if ($banned_options)
|
||||
{
|
||||
$options .= '<optgroup label="' . $user->lang['OPTIONS_BANNED'] . '">';
|
||||
$options .= implode('', $banned_options);
|
||||
$options .= '</optgroup>';
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_BAN_END_OPTIONS' => $ban_end_options,
|
||||
'S_BANNED_OPTIONS' => ($banned_options || $excluded_options) ? true : false,
|
||||
'BANNED_OPTIONS' => $options,
|
||||
));
|
||||
}
|
||||
}
|
||||
620
includes/acp/acp_bbcodes.php
Normal file
620
includes/acp/acp_bbcodes.php
Normal file
@@ -0,0 +1,620 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_bbcodes
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $cache, $request, $phpbb_dispatcher, $phpbb_container;
|
||||
global $phpbb_log;
|
||||
|
||||
$user->add_lang('acp/posting');
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$bbcode_id = $request->variable('bbcode', 0);
|
||||
$submit = $request->is_set_post('submit');
|
||||
|
||||
$this->tpl_name = 'acp_bbcodes';
|
||||
$this->page_title = 'ACP_BBCODES';
|
||||
$form_key = 'acp_bbcodes';
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// 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->variable('display_on_posting', 0);
|
||||
|
||||
$bbcode_match = $request->variable('bbcode_match', '');
|
||||
$bbcode_tpl = htmlspecialchars_decode($request->variable('bbcode_tpl', '', true));
|
||||
$bbcode_helpline = $request->variable('bbcode_helpline', '', true);
|
||||
break;
|
||||
}
|
||||
|
||||
// Do major work
|
||||
switch ($action)
|
||||
{
|
||||
case 'edit':
|
||||
case 'add':
|
||||
|
||||
$tpl_ary = 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,
|
||||
);
|
||||
|
||||
$bbcode_tokens = array('TEXT', 'SIMPLETEXT', 'INTTEXT', 'IDENTIFIER', 'NUMBER', 'EMAIL', 'URL', 'LOCAL_URL', 'RELATIVE_URL', 'COLOR');
|
||||
|
||||
/**
|
||||
* Modify custom bbcode template data before we display the add/edit form
|
||||
*
|
||||
* @event core.acp_bbcodes_edit_add
|
||||
* @var string action Type of the action: add|edit
|
||||
* @var array tpl_ary Array with custom bbcode add/edit data
|
||||
* @var int bbcode_id When editing: the bbcode id,
|
||||
* when creating: 0
|
||||
* @var array bbcode_tokens Array of bbcode tokens
|
||||
* @since 3.1.0-a3
|
||||
*/
|
||||
$vars = array('action', 'tpl_ary', 'bbcode_id', 'bbcode_tokens');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_edit_add', compact($vars)));
|
||||
|
||||
$template->assign_vars($tpl_ary);
|
||||
|
||||
foreach ($bbcode_tokens as $token)
|
||||
{
|
||||
$template->assign_block_vars('token', array(
|
||||
'TOKEN' => '{' . $token . '}',
|
||||
'EXPLAIN' => ($token === 'LOCAL_URL') ? $user->lang(array('tokens', $token), generate_board_url() . '/') : $user->lang(array('tokens', $token)),
|
||||
));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
case 'create':
|
||||
|
||||
$sql_ary = $hidden_fields = array();
|
||||
|
||||
/**
|
||||
* Modify custom bbcode data before the modify/create action
|
||||
*
|
||||
* @event core.acp_bbcodes_modify_create
|
||||
* @var string action Type of the action: modify|create
|
||||
* @var array sql_ary Array with new bbcode data
|
||||
* @var int bbcode_id When editing: the bbcode id,
|
||||
* when creating: 0
|
||||
* @var bool display_on_posting Display bbcode on posting form
|
||||
* @var string bbcode_match The bbcode usage string to match
|
||||
* @var string bbcode_tpl The bbcode HTML replacement string
|
||||
* @var string bbcode_helpline The bbcode help line string
|
||||
* @var array hidden_fields Array of hidden fields for use when
|
||||
* submitting form when $warn_text is true
|
||||
* @since 3.1.0-a3
|
||||
*/
|
||||
$vars = array(
|
||||
'action',
|
||||
'sql_ary',
|
||||
'bbcode_id',
|
||||
'display_on_posting',
|
||||
'bbcode_match',
|
||||
'bbcode_tpl',
|
||||
'bbcode_helpline',
|
||||
'hidden_fields',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create', compact($vars)));
|
||||
|
||||
$warn_text = preg_match('%<[^>]*\{text[\d]*\}[^>]*>%i', $bbcode_tpl);
|
||||
if (!$warn_text || confirm_box(true))
|
||||
{
|
||||
$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_merge($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 = (int) $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 > BBCODE_LIMIT)
|
||||
{
|
||||
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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
$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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
$lang = 'BBCODE_EDITED';
|
||||
$log_action = 'LOG_BBCODE_EDIT';
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($data['bbcode_tag']));
|
||||
|
||||
/**
|
||||
* Event after a BBCode has been added or updated
|
||||
*
|
||||
* @event core.acp_bbcodes_modify_create_after
|
||||
* @var string action Type of the action: modify|create
|
||||
* @var int bbcode_id The id of the added or updated bbcode
|
||||
* @var array sql_ary Array with bbcode data (read only)
|
||||
* @since 3.2.4-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'action',
|
||||
'bbcode_id',
|
||||
'sql_ary',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_modify_create_after', compact($vars)));
|
||||
|
||||
trigger_error($user->lang[$lang] . adm_back_link($this->u_action));
|
||||
}
|
||||
else
|
||||
{
|
||||
confirm_box(false, $user->lang['BBCODE_DANGER'], build_hidden_fields(array_merge($hidden_fields, array(
|
||||
'action' => $action,
|
||||
'bbcode' => $bbcode_id,
|
||||
'bbcode_match' => $bbcode_match,
|
||||
'bbcode_tpl' => htmlspecialchars($bbcode_tpl),
|
||||
'bbcode_helpline' => $bbcode_helpline,
|
||||
'display_on_posting' => $display_on_posting,
|
||||
)))
|
||||
, 'confirm_bbcode.html');
|
||||
}
|
||||
|
||||
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))
|
||||
{
|
||||
$bbcode_tag = $row['bbcode_tag'];
|
||||
|
||||
$db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
|
||||
$cache->destroy('sql', BBCODES_TABLE);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BBCODE_DELETE', false, array($bbcode_tag));
|
||||
|
||||
/**
|
||||
* Event after a BBCode has been deleted
|
||||
*
|
||||
* @event core.acp_bbcodes_delete_after
|
||||
* @var string action Type of the action: delete
|
||||
* @var int bbcode_id The id of the deleted bbcode
|
||||
* @var string bbcode_tag The tag of the deleted bbcode
|
||||
* @since 3.2.4-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'action',
|
||||
'bbcode_id',
|
||||
'bbcode_tag',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_delete_after', compact($vars)));
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'MESSAGE_TITLE' => $user->lang['INFORMATION'],
|
||||
'MESSAGE_TEXT' => $user->lang['BBCODE_DELETED'],
|
||||
'REFRESH_DATA' => array(
|
||||
'time' => 3
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
|
||||
'bbcode' => $bbcode_id,
|
||||
'i' => $id,
|
||||
'mode' => $mode,
|
||||
'action' => $action))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
$u_action = $this->u_action;
|
||||
|
||||
$template_data = array(
|
||||
'U_ACTION' => $this->u_action . '&action=add',
|
||||
);
|
||||
|
||||
$sql_ary = array(
|
||||
'SELECT' => 'b.*',
|
||||
'FROM' => array(BBCODES_TABLE => 'b'),
|
||||
'ORDER_BY' => 'b.bbcode_tag',
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify custom bbcode template data before we display the form
|
||||
*
|
||||
* @event core.acp_bbcodes_display_form
|
||||
* @var string action Type of the action: modify|create
|
||||
* @var array sql_ary The SQL array to get custom bbcode data
|
||||
* @var array template_data Array with form template data
|
||||
* @var string u_action The u_action link
|
||||
* @since 3.1.0-a3
|
||||
*/
|
||||
$vars = array('action', 'sql_ary', 'template_data', 'u_action');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_form', compact($vars)));
|
||||
|
||||
$result = $db->sql_query($db->sql_build_query('SELECT', $sql_ary));
|
||||
|
||||
$template->assign_vars($template_data);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$bbcodes_array = array(
|
||||
'BBCODE_TAG' => $row['bbcode_tag'],
|
||||
'U_EDIT' => $u_action . '&action=edit&bbcode=' . $row['bbcode_id'],
|
||||
'U_DELETE' => $u_action . '&action=delete&bbcode=' . $row['bbcode_id'],
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify display of custom bbcodes in the form
|
||||
*
|
||||
* @event core.acp_bbcodes_display_bbcodes
|
||||
* @var array row Array with current bbcode data
|
||||
* @var array bbcodes_array Array of bbcodes template data
|
||||
* @var string u_action The u_action link
|
||||
* @since 3.1.0-a3
|
||||
*/
|
||||
$vars = array('bbcodes_array', 'row', 'u_action');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_bbcodes_display_bbcodes', compact($vars)));
|
||||
|
||||
$template->assign_block_vars('bbcodes', $bbcodes_array);
|
||||
|
||||
}
|
||||
$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);
|
||||
|
||||
// Allow unicode characters for URL|LOCAL_URL|RELATIVE_URL|INTTEXT tokens
|
||||
$utf8 = preg_match('/(URL|LOCAL_URL|RELATIVE_URL|INTTEXT)/', $bbcode_match);
|
||||
|
||||
$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')"
|
||||
),
|
||||
'RELATIVE_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"
|
||||
),
|
||||
'INTTEXT' => array(
|
||||
'!([\p{L}\p{N}\-+,_. ]+)!u' => "$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)',
|
||||
'RELATIVE_URL' => '(?i)(' . str_replace(array('!', '\#'), array('\!', '#'), get_preg_expression('relative_url')) . ')(?-i)',
|
||||
'EMAIL' => '(' . get_preg_expression('email') . ')',
|
||||
'TEXT' => '(.*?)',
|
||||
'SIMPLETEXT' => '([a-zA-Z0-9-+.,_ ]+)',
|
||||
'INTTEXT' => '([\p{L}\p{N}\-+,_. ]+)',
|
||||
'IDENTIFIER' => '([a-zA-Z0-9-_]+)',
|
||||
'COLOR' => '([a-zA-Z]+|#[0-9abcdefABCDEF]+)',
|
||||
'NUMBER' => '([0-9]+)',
|
||||
);
|
||||
|
||||
$pad = 0;
|
||||
$modifiers = 'i';
|
||||
$modifiers .= ($utf8) ? 'u' : '';
|
||||
|
||||
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 + count(array_unique($repad[0]));
|
||||
$replace = preg_replace_callback('/(?<!\\\\)\$([0-9]+)/', function ($match) use ($pad) {
|
||||
return '${' . ($match[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);
|
||||
|
||||
// Prepend the board url to local relative links
|
||||
$replace_prepend = ($token_type === 'LOCAL_URL') ? generate_board_url() . '/' : '';
|
||||
|
||||
$sp_replace = str_replace($token, $replace_prepend . '${' . ($n + 1) . '}', $sp_replace);
|
||||
}
|
||||
|
||||
$fp_match = '!' . $fp_match . '!' . $modifiers;
|
||||
$sp_match = '!' . $sp_match . '!s' . (($utf8) ? 'u' : '');
|
||||
|
||||
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_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
|
||||
return strtolower($match[0]);
|
||||
}, $fp_match);
|
||||
$fp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
|
||||
return strtolower($match[0]);
|
||||
}, $fp_replace);
|
||||
$sp_match = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
|
||||
return strtolower($match[0]);
|
||||
}, $sp_match);
|
||||
$sp_replace = preg_replace_callback('#\[/?' . $bbcode_search . '#i', function ($match) {
|
||||
return strtolower($match[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
|
||||
);
|
||||
}
|
||||
}
|
||||
1178
includes/acp/acp_board.php
Normal file
1178
includes/acp/acp_board.php
Normal file
File diff suppressed because it is too large
Load Diff
427
includes/acp/acp_bots.php
Normal file
427
includes/acp/acp_bots.php
Normal file
@@ -0,0 +1,427 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_bots
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $config, $db, $user, $template, $cache, $request, $phpbb_log;
|
||||
global $phpbb_root_path, $phpEx;
|
||||
|
||||
$action = $request->variable('action', '');
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
$mark = $request->variable('mark', array(0));
|
||||
$bot_id = $request->variable('id', 0);
|
||||
|
||||
if (isset($_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 || count($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 || count($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 || count($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 (count($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');
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_DELETE', false, array(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':
|
||||
|
||||
if (!function_exists('user_update_name'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
$bot_row = array(
|
||||
'bot_name' => $request->variable('bot_name', '', true),
|
||||
'bot_agent' => $request->variable('bot_agent', ''),
|
||||
'bot_ip' => $request->variable('bot_ip', ''),
|
||||
'bot_active' => $request->variable('bot_active', true),
|
||||
'bot_lang' => $request->variable('bot_lang', $config['default_lang']),
|
||||
'bot_style' => $request->variable('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 (!count($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 = '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');
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_BOT_' . $log, false, array($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' => (count($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' => (count($error)) ? true : false,
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if ($request->is_ajax() && ($action == 'activate' || $action == 'deactivate'))
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'text' => $user->lang['BOT_' . (($action == 'activate') ? 'DE' : '') . 'ACTIVATE'],
|
||||
));
|
||||
}
|
||||
|
||||
$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;
|
||||
}
|
||||
}
|
||||
190
includes/acp/acp_captcha.php
Normal file
190
includes/acp/acp_captcha.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_captcha
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $user, $template, $phpbb_log, $request;
|
||||
global $config, $phpbb_container;
|
||||
|
||||
$user->add_lang('acp/board');
|
||||
|
||||
/* @var $factory \phpbb\captcha\factory */
|
||||
$factory = $phpbb_container->get('captcha.factory');
|
||||
$captchas = $factory->get_captcha_types();
|
||||
|
||||
$selected = $request->variable('select_captcha', $config['captcha_plugin']);
|
||||
$selected = (isset($captchas['available'][$selected]) || isset($captchas['unavailable'][$selected])) ? $selected : $config['captcha_plugin'];
|
||||
$configure = $request->variable('configure', false);
|
||||
|
||||
// Oh, they are just here for the view
|
||||
if (isset($_GET['captcha_demo']))
|
||||
{
|
||||
$this->deliver_demo($selected);
|
||||
}
|
||||
|
||||
// Delegate
|
||||
if ($configure)
|
||||
{
|
||||
$config_captcha = $factory->get_instance($selected);
|
||||
$config_captcha->acp_page($id, $this);
|
||||
}
|
||||
else
|
||||
{
|
||||
$config_vars = array(
|
||||
'enable_confirm' => array(
|
||||
'tpl' => 'REG_ENABLE',
|
||||
'default' => false,
|
||||
'validate' => 'bool',
|
||||
'lang' => 'VISUAL_CONFIRM_REG',
|
||||
),
|
||||
'enable_post_confirm' => array(
|
||||
'tpl' => 'POST_ENABLE',
|
||||
'default' => false,
|
||||
'validate' => 'bool',
|
||||
'lang' => 'VISUAL_CONFIRM_POST',
|
||||
),
|
||||
'confirm_refresh' => array(
|
||||
'tpl' => 'CONFIRM_REFRESH',
|
||||
'default' => false,
|
||||
'validate' => 'bool',
|
||||
'lang' => 'VISUAL_CONFIRM_REFRESH',
|
||||
),
|
||||
'max_reg_attempts' => array(
|
||||
'tpl' => 'REG_LIMIT',
|
||||
'default' => 0,
|
||||
'validate' => 'int:0:99999',
|
||||
'lang' => 'REG_LIMIT',
|
||||
),
|
||||
'max_login_attempts' => array(
|
||||
'tpl' => 'MAX_LOGIN_ATTEMPTS',
|
||||
'default' => 0,
|
||||
'validate' => 'int:0:99999',
|
||||
'lang' => 'MAX_LOGIN_ATTEMPTS',
|
||||
),
|
||||
);
|
||||
|
||||
$this->tpl_name = 'acp_captcha';
|
||||
$this->page_title = 'ACP_VC_SETTINGS';
|
||||
$form_key = 'acp_captcha';
|
||||
add_form_key($form_key);
|
||||
|
||||
$submit = $request->variable('main_submit', false);
|
||||
$error = $cfg_array = array();
|
||||
|
||||
if ($submit)
|
||||
{
|
||||
foreach ($config_vars as $config_var => $options)
|
||||
{
|
||||
$cfg_array[$config_var] = $request->variable($config_var, $options['default']);
|
||||
}
|
||||
validate_config_vars($config_vars, $cfg_array, $error);
|
||||
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
$error[] = $user->lang['FORM_INVALID'];
|
||||
}
|
||||
if ($error)
|
||||
{
|
||||
$submit = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($submit)
|
||||
{
|
||||
foreach ($cfg_array as $key => $value)
|
||||
{
|
||||
$config->set($key, $value);
|
||||
}
|
||||
|
||||
if ($selected !== $config['captcha_plugin'])
|
||||
{
|
||||
// sanity check
|
||||
if (isset($captchas['available'][$selected]))
|
||||
{
|
||||
$old_captcha = $factory->get_instance($config['captcha_plugin']);
|
||||
$old_captcha->uninstall();
|
||||
|
||||
$config->set('captcha_plugin', $selected);
|
||||
$new_captcha = $factory->get_instance($config['captcha_plugin']);
|
||||
$new_captcha->install();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_VISUAL');
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error($user->lang['CAPTCHA_UNAVAILABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
trigger_error($user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
|
||||
}
|
||||
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)
|
||||
{
|
||||
$current = ($selected !== false && $value == $selected) ? ' selected="selected"' : '';
|
||||
$captcha_select .= '<option value="' . $value . '"' . $current . ' class="disabled-option">' . $user->lang($title) . '</option>';
|
||||
}
|
||||
|
||||
$demo_captcha = $factory->get_instance($selected);
|
||||
|
||||
foreach ($config_vars as $config_var => $options)
|
||||
{
|
||||
$template->assign_var($options['tpl'], (isset($_POST[$config_var])) ? $request->variable($config_var, $options['default']) : $config[$config_var]) ;
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'CAPTCHA_PREVIEW_TPL' => $demo_captcha->get_demo_template($id),
|
||||
'S_CAPTCHA_HAS_CONFIG' => $demo_captcha->has_config(),
|
||||
'CAPTCHA_SELECT' => $captcha_select,
|
||||
'ERROR_MSG' => implode('<br />', $error),
|
||||
|
||||
'U_ACTION' => $this->u_action,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point for delivering image CAPTCHAs in the ACP.
|
||||
*/
|
||||
function deliver_demo($selected)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
$captcha = $phpbb_container->get('captcha.factory')->get_instance($selected);
|
||||
$captcha->init(CONFIRM_REG);
|
||||
$captcha->execute_demo();
|
||||
|
||||
garbage_collection();
|
||||
exit_handler();
|
||||
}
|
||||
}
|
||||
138
includes/acp/acp_contact.php
Normal file
138
includes/acp/acp_contact.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @package acp
|
||||
*/
|
||||
class acp_contact
|
||||
{
|
||||
public $u_action;
|
||||
|
||||
public function main($id, $mode)
|
||||
{
|
||||
global $user, $request, $template;
|
||||
global $config, $phpbb_root_path, $phpEx, $phpbb_container;
|
||||
|
||||
$user->add_lang(array('acp/board', 'posting'));
|
||||
|
||||
$this->tpl_name = 'acp_contact';
|
||||
$this->page_title = 'ACP_CONTACT_SETTINGS';
|
||||
$form_name = 'acp_contact';
|
||||
add_form_key($form_name);
|
||||
$error = '';
|
||||
|
||||
if (!function_exists('display_custom_bbcodes'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
|
||||
}
|
||||
if (!class_exists('parse_message'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/message_parser.' . $phpEx);
|
||||
}
|
||||
|
||||
/* @var $config_text \phpbb\config\db_text */
|
||||
$config_text = $phpbb_container->get('config_text');
|
||||
|
||||
$contact_admin_data = $config_text->get_array(array(
|
||||
'contact_admin_info',
|
||||
'contact_admin_info_uid',
|
||||
'contact_admin_info_bitfield',
|
||||
'contact_admin_info_flags',
|
||||
));
|
||||
|
||||
$contact_admin_info = $contact_admin_data['contact_admin_info'];
|
||||
$contact_admin_info_uid = $contact_admin_data['contact_admin_info_uid'];
|
||||
$contact_admin_info_bitfield= $contact_admin_data['contact_admin_info_bitfield'];
|
||||
$contact_admin_info_flags = $contact_admin_data['contact_admin_info_flags'];
|
||||
|
||||
if ($request->is_set_post('submit') || $request->is_set_post('preview'))
|
||||
{
|
||||
if (!check_form_key($form_name))
|
||||
{
|
||||
$error = $user->lang('FORM_INVALID');
|
||||
}
|
||||
|
||||
$contact_admin_info = $request->variable('contact_admin_info', '', true);
|
||||
|
||||
generate_text_for_storage(
|
||||
$contact_admin_info,
|
||||
$contact_admin_info_uid,
|
||||
$contact_admin_info_bitfield,
|
||||
$contact_admin_info_flags,
|
||||
!$request->variable('disable_bbcode', false),
|
||||
!$request->variable('disable_magic_url', false),
|
||||
!$request->variable('disable_smilies', false)
|
||||
);
|
||||
|
||||
if (empty($error) && $request->is_set_post('submit'))
|
||||
{
|
||||
$config->set('contact_admin_form_enable', $request->variable('contact_admin_form_enable', false));
|
||||
|
||||
$config_text->set_array(array(
|
||||
'contact_admin_info' => $contact_admin_info,
|
||||
'contact_admin_info_uid' => $contact_admin_info_uid,
|
||||
'contact_admin_info_bitfield' => $contact_admin_info_bitfield,
|
||||
'contact_admin_info_flags' => $contact_admin_info_flags,
|
||||
));
|
||||
|
||||
trigger_error($user->lang['CONTACT_US_INFO_UPDATED'] . adm_back_link($this->u_action));
|
||||
}
|
||||
}
|
||||
|
||||
$contact_admin_info_preview = '';
|
||||
if ($request->is_set_post('preview'))
|
||||
{
|
||||
$contact_admin_info_preview = generate_text_for_display($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_bitfield, $contact_admin_info_flags);
|
||||
}
|
||||
|
||||
$contact_admin_edit = generate_text_for_edit($contact_admin_info, $contact_admin_info_uid, $contact_admin_info_flags);
|
||||
|
||||
/** @var \phpbb\controller\helper $controller_helper */
|
||||
$controller_helper = $phpbb_container->get('controller.helper');
|
||||
|
||||
$template->assign_vars(array(
|
||||
'ERRORS' => $error,
|
||||
'CONTACT_ENABLED' => $config['contact_admin_form_enable'],
|
||||
|
||||
'CONTACT_US_INFO' => $contact_admin_edit['text'],
|
||||
'CONTACT_US_INFO_PREVIEW' => $contact_admin_info_preview,
|
||||
|
||||
'S_BBCODE_DISABLE_CHECKED' => !$contact_admin_edit['allow_bbcode'],
|
||||
'S_SMILIES_DISABLE_CHECKED' => !$contact_admin_edit['allow_smilies'],
|
||||
'S_MAGIC_URL_DISABLE_CHECKED' => !$contact_admin_edit['allow_urls'],
|
||||
|
||||
'BBCODE_STATUS' => $user->lang('BBCODE_IS_ON', '<a href="' . $controller_helper->route('phpbb_help_bbcode_controller') . '">', '</a>'),
|
||||
'SMILIES_STATUS' => $user->lang['SMILIES_ARE_ON'],
|
||||
'IMG_STATUS' => $user->lang['IMAGES_ARE_ON'],
|
||||
'FLASH_STATUS' => $user->lang['FLASH_IS_ON'],
|
||||
'URL_STATUS' => $user->lang['URL_IS_ON'],
|
||||
|
||||
'S_BBCODE_ALLOWED' => true,
|
||||
'S_SMILIES_ALLOWED' => true,
|
||||
'S_BBCODE_IMG' => true,
|
||||
'S_BBCODE_FLASH' => true,
|
||||
'S_LINKS_ALLOWED' => true,
|
||||
));
|
||||
|
||||
// Assigning custom bbcodes
|
||||
display_custom_bbcodes();
|
||||
}
|
||||
}
|
||||
622
includes/acp/acp_database.php
Normal file
622
includes/acp/acp_database.php
Normal file
@@ -0,0 +1,622 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_database
|
||||
{
|
||||
var $db_tools;
|
||||
var $u_action;
|
||||
public $page_title;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $cache, $db, $user, $template, $table_prefix, $request;
|
||||
global $phpbb_root_path, $phpbb_container, $phpbb_log;
|
||||
|
||||
$this->db_tools = $phpbb_container->get('dbal.tools');
|
||||
|
||||
$user->add_lang('acp/database');
|
||||
|
||||
$this->tpl_name = 'acp_database';
|
||||
$this->page_title = 'ACP_DATABASE';
|
||||
|
||||
$action = $request->variable('action', '');
|
||||
|
||||
$form_key = 'acp_database';
|
||||
add_form_key($form_key);
|
||||
|
||||
$template->assign_vars(array(
|
||||
'MODE' => $mode
|
||||
));
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
case 'backup':
|
||||
|
||||
$this->page_title = 'ACP_BACKUP';
|
||||
|
||||
switch ($action)
|
||||
{
|
||||
case 'download':
|
||||
$type = $request->variable('type', '');
|
||||
$table = array_intersect($this->db_tools->sql_list_tables(), $request->variable('table', array('')));
|
||||
$format = $request->variable('method', '');
|
||||
$where = $request->variable('where', '');
|
||||
|
||||
if (!count($table))
|
||||
{
|
||||
trigger_error($user->lang['TABLE_SELECT_ERROR'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$store = $structure = $schema_data = false;
|
||||
|
||||
if ($where == 'store')
|
||||
{
|
||||
$store = true;
|
||||
}
|
||||
|
||||
if ($type == 'full' || $type == 'structure')
|
||||
{
|
||||
$structure = true;
|
||||
}
|
||||
|
||||
if ($type == 'full' || $type == 'data')
|
||||
{
|
||||
$schema_data = true;
|
||||
}
|
||||
|
||||
@set_time_limit(1200);
|
||||
@set_time_limit(0);
|
||||
|
||||
$time = time();
|
||||
|
||||
$filename = 'backup_' . $time . '_' . unique_id();
|
||||
|
||||
/** @var phpbb\db\extractor\extractor_interface $extractor Database extractor */
|
||||
$extractor = $phpbb_container->get('dbal.extractor');
|
||||
$extractor->init_extractor($format, $filename, $time, false, $store);
|
||||
|
||||
$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->get_sql_layer())
|
||||
{
|
||||
case 'sqlite3':
|
||||
$extractor->flush('DELETE FROM ' . $table_name . ";\n");
|
||||
break;
|
||||
|
||||
case 'mssql_odbc':
|
||||
case 'mssqlnative':
|
||||
$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();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_BACKUP');
|
||||
|
||||
trigger_error($user->lang['BACKUP_SUCCESS'] . adm_back_link($this->u_action));
|
||||
break;
|
||||
|
||||
default:
|
||||
$tables = $this->db_tools->sql_list_tables();
|
||||
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->variable('delete', '');
|
||||
$file = $request->variable('file', '');
|
||||
|
||||
$backup_info = $this->get_backup_file($phpbb_root_path . 'store/', $file);
|
||||
|
||||
if (empty($backup_info) || !is_readable($backup_info['file_name']))
|
||||
{
|
||||
trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if ($delete)
|
||||
{
|
||||
if (confirm_box(true))
|
||||
{
|
||||
unlink($backup_info['file_name']);
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, '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 if (confirm_box(true))
|
||||
{
|
||||
switch ($backup_info['extensions'])
|
||||
{
|
||||
case 'sql':
|
||||
$fp = fopen($backup_info['file_name'], 'rb');
|
||||
$read = 'fread';
|
||||
$seek = 'fseek';
|
||||
$eof = 'feof';
|
||||
$close = 'fclose';
|
||||
$fgetd = 'fgetd';
|
||||
break;
|
||||
|
||||
case 'sql.bz2':
|
||||
$fp = bzopen($backup_info['file_name'], 'r');
|
||||
$read = 'bzread';
|
||||
$seek = '';
|
||||
$eof = 'feof';
|
||||
$close = 'bzclose';
|
||||
$fgetd = 'fgetd_seekless';
|
||||
break;
|
||||
|
||||
case 'sql.gz':
|
||||
$fp = gzopen($backup_info['file_name'], 'rb');
|
||||
$read = 'gzread';
|
||||
$seek = 'gzseek';
|
||||
$eof = 'gzeof';
|
||||
$close = 'gzclose';
|
||||
$fgetd = 'fgetd';
|
||||
break;
|
||||
|
||||
default:
|
||||
trigger_error($user->lang['BACKUP_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
switch ($db->get_sql_layer())
|
||||
{
|
||||
case 'mysql':
|
||||
case 'mysql4':
|
||||
case 'mysqli':
|
||||
case 'sqlite3':
|
||||
while (($sql = $fgetd($fp, ";\n", $read, $seek, $eof)) !== false)
|
||||
{
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
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->get_db_connect_id(), $sub . "\n");
|
||||
}
|
||||
pg_put_line($db->get_db_connect_id(), "\\.\n");
|
||||
pg_end_copy($db->get_db_connect_id());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'oracle':
|
||||
while (($sql = $fgetd($fp, "/\n", $read, $seek, $eof)) !== false)
|
||||
{
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'mssql_odbc':
|
||||
case 'mssqlnative':
|
||||
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();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DB_RESTORE');
|
||||
trigger_error($user->lang['RESTORE_SUCCESS'] . adm_back_link($this->u_action));
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
confirm_box(false, $user->lang['RESTORE_SELECTED_BACKUP'], build_hidden_fields(array('file' => $file)));
|
||||
}
|
||||
|
||||
default:
|
||||
$backup_files = $this->get_file_list($phpbb_root_path . 'store/');
|
||||
|
||||
if (!empty($backup_files))
|
||||
{
|
||||
krsort($backup_files);
|
||||
|
||||
foreach ($backup_files as $name => $file)
|
||||
{
|
||||
$template->assign_block_vars('files', array(
|
||||
'FILE' => sha1($file),
|
||||
'NAME' => $user->format_date($name, 'd-m-Y H:i', true),
|
||||
'SUPPORTED' => true,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'U_ACTION' => $this->u_action . '&action=submit'
|
||||
));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get backup file from file hash
|
||||
*
|
||||
* @param string $directory Relative path to directory
|
||||
* @param string $file_hash Hash of selected file
|
||||
*
|
||||
* @return array Backup file data or empty array if unable to find file
|
||||
*/
|
||||
protected function get_backup_file($directory, $file_hash)
|
||||
{
|
||||
$backup_data = [];
|
||||
|
||||
$file_list = $this->get_file_list($directory);
|
||||
$supported_extensions = $this->get_supported_extensions();
|
||||
|
||||
foreach ($file_list as $file)
|
||||
{
|
||||
preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches);
|
||||
if (sha1($file) === $file_hash && in_array($matches[2], $supported_extensions))
|
||||
{
|
||||
$backup_data = [
|
||||
'file_name' => $directory . $file,
|
||||
'extension' => $matches[2],
|
||||
];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $backup_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get backup file list for directory
|
||||
*
|
||||
* @param string $directory Relative path to backup directory
|
||||
*
|
||||
* @return array List of backup files in specified directory
|
||||
*/
|
||||
protected function get_file_list($directory)
|
||||
{
|
||||
$supported_extensions = $this->get_supported_extensions();
|
||||
|
||||
$dh = @opendir($directory);
|
||||
|
||||
$backup_files = [];
|
||||
|
||||
if ($dh)
|
||||
{
|
||||
while (($file = readdir($dh)) !== false)
|
||||
{
|
||||
if (preg_match('#^backup_(\d{10,})_(?:[a-z\d]{16}|[a-z\d]{32})\.(sql(?:\.(?:gz|bz2))?)$#i', $file, $matches))
|
||||
{
|
||||
if (in_array($matches[2], $supported_extensions))
|
||||
{
|
||||
$backup_files[(int) $matches[1]] = $file;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
}
|
||||
|
||||
return $backup_files;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported extensions for backup
|
||||
*
|
||||
* @return array List of supported extensions
|
||||
*/
|
||||
protected function get_supported_extensions()
|
||||
{
|
||||
$extensions = ['sql'];
|
||||
$available_methods = ['sql.gz' => 'zlib', 'sql.bz2' => 'bz2'];
|
||||
|
||||
foreach ($available_methods as $type => $module)
|
||||
{
|
||||
if (!@extension_loaded($module))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$extensions[] = $type;
|
||||
}
|
||||
|
||||
return $extensions;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (count($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);
|
||||
$data = preg_split('/[\0\b\f\'\/]/', $text);
|
||||
preg_match_all('/[\0\r\b\f\'\/]/', $text, $matches);
|
||||
|
||||
$val = array();
|
||||
|
||||
foreach ($data as $value)
|
||||
{
|
||||
if (strlen($value))
|
||||
{
|
||||
$val[] = "'" . $value . "'";
|
||||
}
|
||||
if (count($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 (count($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 (!count($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 (count($array))
|
||||
{
|
||||
return array_shift($array);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
115
includes/acp/acp_disallow.php
Normal file
115
includes/acp/acp_disallow.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_disallow
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $cache, $phpbb_log, $request;
|
||||
|
||||
$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 = (isset($_POST['disallow'])) ? true : false;
|
||||
$allow = (isset($_POST['allow'])) ? true : false;
|
||||
|
||||
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('*', '%', $request->variable('disallowed_user', '', true));
|
||||
|
||||
if (!$disallowed_user)
|
||||
{
|
||||
trigger_error($user->lang['NO_USERNAME_SPECIFIED'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$sql = 'SELECT disallow_id
|
||||
FROM ' . DISALLOW_TABLE . "
|
||||
WHERE disallow_username = '" . $db->sql_escape($disallowed_user) . "'";
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if ($row)
|
||||
{
|
||||
trigger_error($user->lang['DISALLOWED_ALREADY'] . 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'];
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_DISALLOW_ADD', false, array(str_replace('%', '*', $disallowed_user)));
|
||||
|
||||
trigger_error($message . adm_back_link($this->u_action));
|
||||
}
|
||||
else if ($allow)
|
||||
{
|
||||
$disallowed_id = $request->variable('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');
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, '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)
|
||||
);
|
||||
}
|
||||
}
|
||||
351
includes/acp/acp_email.php
Normal file
351
includes/acp/acp_email.php
Normal file
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_email
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $config, $db, $user, $template, $phpbb_log, $request;
|
||||
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_dispatcher;
|
||||
|
||||
$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 = (isset($_POST['submit'])) ? true : false;
|
||||
$error = array();
|
||||
|
||||
$usernames = $request->variable('usernames', '', true);
|
||||
$usernames = (!empty($usernames)) ? explode("\n", $usernames) : array();
|
||||
$group_id = $request->variable('g', 0);
|
||||
$subject = $request->variable('subject', '', true);
|
||||
$message = $request->variable('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 = (isset($_POST['send_immediately'])) ? false : true;
|
||||
$priority = $request->variable('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 (!count($error))
|
||||
{
|
||||
if (!empty($usernames))
|
||||
{
|
||||
// If giving usernames the admin is able to email inactive users too...
|
||||
$sql_ary = array(
|
||||
'SELECT' => 'username, user_email, user_jabber, user_notify_type, user_lang',
|
||||
'FROM' => array(
|
||||
USERS_TABLE => '',
|
||||
),
|
||||
'WHERE' => $db->sql_in_set('username_clean', array_map('utf8_clean_string', $usernames)) . '
|
||||
AND user_allow_massemail = 1',
|
||||
'ORDER_BY' => 'user_lang, user_notify_type',
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($group_id)
|
||||
{
|
||||
$sql_ary = array(
|
||||
'SELECT' => 'u.user_email, u.username, u.username_clean, u.user_lang, u.user_jabber, u.user_notify_type',
|
||||
'FROM' => array(
|
||||
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_ary = array(
|
||||
'SELECT' => 'u.username, u.username_clean, u.user_email, u.user_jabber, u.user_lang, u.user_notify_type',
|
||||
'FROM' => array(
|
||||
USERS_TABLE => 'u',
|
||||
),
|
||||
'WHERE' => 'u.user_allow_massemail = 1
|
||||
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')',
|
||||
'ORDER_BY' => 'u.user_lang, u.user_notify_type',
|
||||
);
|
||||
}
|
||||
|
||||
// Mail banned or not
|
||||
if (!isset($_REQUEST['mail_banned_flag']))
|
||||
{
|
||||
$sql_ary['WHERE'] .= ' AND (b.ban_id IS NULL
|
||||
OR b.ban_exclude = 1)';
|
||||
$sql_ary['LEFT_JOIN'] = array(
|
||||
array(
|
||||
'FROM' => array(
|
||||
BANLIST_TABLE => 'b',
|
||||
),
|
||||
'ON' => 'u.user_id = b.ban_userid',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Modify sql query to change the list of users the email is sent to
|
||||
*
|
||||
* @event core.acp_email_modify_sql
|
||||
* @var array sql_ary Array which is used to build the sql query
|
||||
* @since 3.1.2-RC1
|
||||
*/
|
||||
$vars = array('sql_ary');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_email_modify_sql', compact($vars)));
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_ary);
|
||||
$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
|
||||
// Maximum number of bcc recipients
|
||||
$max_chunk_size = (int) $config['email_max_chunk_size'];
|
||||
$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 (count($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
|
||||
if (!class_exists('messenger'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
|
||||
}
|
||||
|
||||
if (!function_exists('get_group_name'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
$messenger = new messenger($use_queue);
|
||||
|
||||
$errored = false;
|
||||
|
||||
$email_template = 'admin_send_email';
|
||||
$template_data = array(
|
||||
'CONTACT_EMAIL' => phpbb_get_board_contact($config, $phpEx),
|
||||
'MESSAGE' => htmlspecialchars_decode($message),
|
||||
);
|
||||
$generate_log_entry = true;
|
||||
|
||||
/**
|
||||
* Modify email template data before the emails are sent
|
||||
*
|
||||
* @event core.acp_email_send_before
|
||||
* @var string email_template The template to be used for sending the email
|
||||
* @var string subject The subject of the email
|
||||
* @var array template_data Array with template data assigned to email template
|
||||
* @var bool generate_log_entry If false, no log entry will be created
|
||||
* @var array usernames Usernames which will be displayed in log entry, if it will be created
|
||||
* @var int group_id The group this email will be sent to
|
||||
* @var bool use_queue If true, email queue will be used for sending
|
||||
* @var int priority Priority of sent emails
|
||||
* @since 3.1.3-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'email_template',
|
||||
'subject',
|
||||
'template_data',
|
||||
'generate_log_entry',
|
||||
'usernames',
|
||||
'group_id',
|
||||
'use_queue',
|
||||
'priority',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_email_send_before', compact($vars)));
|
||||
|
||||
for ($i = 0, $size = count($email_list); $i < $size; $i++)
|
||||
{
|
||||
$used_lang = $email_list[$i][0]['lang'];
|
||||
$used_method = $email_list[$i][0]['method'];
|
||||
|
||||
for ($j = 0, $list_size = count($email_list[$i]); $j < $list_size; $j++)
|
||||
{
|
||||
$email_row = $email_list[$i][$j];
|
||||
|
||||
$messenger->{((count($email_list[$i]) == 1) ? 'to' : 'bcc')}($email_row['email'], $email_row['name']);
|
||||
$messenger->im($email_row['jabber'], $email_row['name']);
|
||||
}
|
||||
|
||||
$messenger->template($email_template, $used_lang);
|
||||
|
||||
$messenger->anti_abuse_headers($config, $user);
|
||||
|
||||
$messenger->subject(htmlspecialchars_decode($subject));
|
||||
$messenger->set_mail_priority($priority);
|
||||
|
||||
$messenger->assign_vars($template_data);
|
||||
|
||||
if (!($messenger->send($used_method)))
|
||||
{
|
||||
$errored = true;
|
||||
}
|
||||
}
|
||||
unset($email_list);
|
||||
|
||||
$messenger->save_queue();
|
||||
|
||||
if ($generate_log_entry)
|
||||
{
|
||||
if (!empty($usernames))
|
||||
{
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array(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'];
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MASS_EMAIL', false, array($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.$phpEx", '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 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_data = array(
|
||||
'S_WARNING' => (count($error)) ? true : false,
|
||||
'WARNING_MSG' => (count($error)) ? implode('<br />', $error) : '',
|
||||
'U_ACTION' => $this->u_action,
|
||||
'S_GROUP_OPTIONS' => $select_list,
|
||||
'USERNAMES' => implode("\n", $usernames),
|
||||
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", 'mode=searchuser&form=acp_email&field=usernames'),
|
||||
'SUBJECT' => $subject,
|
||||
'MESSAGE' => $message,
|
||||
'S_PRIORITY_OPTIONS' => $s_priority_options,
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify custom email template data before we display the form
|
||||
*
|
||||
* @event core.acp_email_display
|
||||
* @var array template_data Array with template data assigned to email template
|
||||
* @var array exclude Array with groups which are excluded from group selection
|
||||
* @var array usernames Usernames which will be displayed in form
|
||||
*
|
||||
* @since 3.1.4-RC1
|
||||
*/
|
||||
$vars = array('template_data', 'exclude', 'usernames');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_email_display', compact($vars)));
|
||||
|
||||
$template->assign_vars($template_data);
|
||||
}
|
||||
}
|
||||
665
includes/acp/acp_extensions.php
Normal file
665
includes/acp/acp_extensions.php
Normal file
@@ -0,0 +1,665 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
use phpbb\exception\exception_interface;
|
||||
use phpbb\exception\version_check_exception;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_extensions
|
||||
{
|
||||
var $u_action;
|
||||
var $tpl_name;
|
||||
var $page_title;
|
||||
|
||||
private $config;
|
||||
private $template;
|
||||
private $user;
|
||||
private $log;
|
||||
private $request;
|
||||
private $phpbb_dispatcher;
|
||||
private $ext_manager;
|
||||
private $phpbb_container;
|
||||
private $php_ini;
|
||||
|
||||
function main()
|
||||
{
|
||||
// Start the page
|
||||
global $config, $user, $template, $request, $phpbb_extension_manager, $phpbb_root_path, $phpbb_log, $phpbb_dispatcher, $phpbb_container;
|
||||
|
||||
$this->config = $config;
|
||||
$this->template = $template;
|
||||
$this->user = $user;
|
||||
$this->request = $request;
|
||||
$this->log = $phpbb_log;
|
||||
$this->phpbb_dispatcher = $phpbb_dispatcher;
|
||||
$this->ext_manager = $phpbb_extension_manager;
|
||||
$this->phpbb_container = $phpbb_container;
|
||||
$this->php_ini = $this->phpbb_container->get('php_ini');
|
||||
|
||||
$this->user->add_lang(array('install', 'acp/extensions', 'migrator'));
|
||||
|
||||
$this->page_title = 'ACP_EXTENSIONS';
|
||||
|
||||
$action = $this->request->variable('action', 'list');
|
||||
$ext_name = $this->request->variable('ext_name', '');
|
||||
|
||||
// What is a safe limit of execution time? Half the max execution time should be safe.
|
||||
$safe_time_limit = ($this->php_ini->getNumeric('max_execution_time') / 2);
|
||||
$start_time = time();
|
||||
|
||||
// Cancel action
|
||||
if ($this->request->is_set_post('cancel'))
|
||||
{
|
||||
$action = 'list';
|
||||
$ext_name = '';
|
||||
}
|
||||
|
||||
if (in_array($action, array('enable', 'disable', 'delete_data')) && !check_link_hash($this->request->variable('hash', ''), $action . '.' . $ext_name))
|
||||
{
|
||||
trigger_error('FORM_INVALID', E_USER_WARNING);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event to run a specific action on extension
|
||||
*
|
||||
* @event core.acp_extensions_run_action_before
|
||||
* @var string action Action to run; if the event completes execution of the action, should be set to 'none'
|
||||
* @var string u_action Url we are at
|
||||
* @var string ext_name Extension name from request
|
||||
* @var int safe_time_limit Safe limit of execution time
|
||||
* @var int start_time Start time
|
||||
* @var string tpl_name Template file to load
|
||||
* @since 3.1.11-RC1
|
||||
* @changed 3.2.1-RC1 Renamed to core.acp_extensions_run_action_before, added tpl_name, added action 'none'
|
||||
*/
|
||||
$u_action = $this->u_action;
|
||||
$tpl_name = '';
|
||||
$vars = array('action', 'u_action', 'ext_name', 'safe_time_limit', 'start_time', 'tpl_name');
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.acp_extensions_run_action_before', compact($vars)));
|
||||
|
||||
// In case they have been updated by the event
|
||||
$this->u_action = $u_action;
|
||||
$this->tpl_name = $tpl_name;
|
||||
|
||||
// If they've specified an extension, let's load the metadata manager and validate it.
|
||||
if ($ext_name)
|
||||
{
|
||||
$md_manager = $this->ext_manager->create_extension_metadata_manager($ext_name);
|
||||
|
||||
try
|
||||
{
|
||||
$md_manager->get_metadata('all');
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
// What are we doing?
|
||||
switch ($action)
|
||||
{
|
||||
case 'none':
|
||||
// Intentionally empty, used by extensions that execute additional actions in the prior event
|
||||
break;
|
||||
|
||||
case 'set_config_version_check_force_unstable':
|
||||
$force_unstable = $this->request->variable('force_unstable', false);
|
||||
|
||||
if ($force_unstable)
|
||||
{
|
||||
$s_hidden_fields = build_hidden_fields(array(
|
||||
'force_unstable' => $force_unstable,
|
||||
));
|
||||
|
||||
confirm_box(false, $this->user->lang('EXTENSION_FORCE_UNSTABLE_CONFIRM'), $s_hidden_fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->config->set('extension_force_unstable', false);
|
||||
trigger_error($this->user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'list':
|
||||
default:
|
||||
if (confirm_box(true))
|
||||
{
|
||||
$this->config->set('extension_force_unstable', true);
|
||||
trigger_error($this->user->lang['CONFIG_UPDATED'] . adm_back_link($this->u_action));
|
||||
}
|
||||
|
||||
$this->list_enabled_exts();
|
||||
$this->list_disabled_exts();
|
||||
$this->list_available_exts();
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=list&versioncheck_force=1',
|
||||
'FORCE_UNSTABLE' => $this->config['extension_force_unstable'],
|
||||
'U_ACTION' => $this->u_action,
|
||||
));
|
||||
|
||||
$this->tpl_name = 'acp_ext_list';
|
||||
break;
|
||||
|
||||
case 'enable_pre':
|
||||
try
|
||||
{
|
||||
$md_manager->validate_enable();
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$extension = $this->ext_manager->get_extension($ext_name);
|
||||
if (!$extension->is_enableable())
|
||||
{
|
||||
trigger_error($this->user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if ($this->ext_manager->is_enabled($ext_name))
|
||||
{
|
||||
redirect($this->u_action);
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_ext_enable';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'PRE' => true,
|
||||
'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_ENABLE_CONFIRM', $md_manager->get_metadata('display-name')),
|
||||
'U_ENABLE' => $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name),
|
||||
));
|
||||
break;
|
||||
|
||||
case 'enable':
|
||||
try
|
||||
{
|
||||
$md_manager->validate_enable();
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
trigger_error($message . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$extension = $this->ext_manager->get_extension($ext_name);
|
||||
if (!$extension->is_enableable())
|
||||
{
|
||||
trigger_error($this->user->lang['EXTENSION_NOT_ENABLEABLE'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while ($this->ext_manager->enable_step($ext_name))
|
||||
{
|
||||
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
|
||||
if ((time() - $start_time) >= $safe_time_limit)
|
||||
{
|
||||
$this->template->assign_var('S_NEXT_STEP', true);
|
||||
|
||||
meta_refresh(0, $this->u_action . '&action=enable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('enable.' . $ext_name));
|
||||
}
|
||||
}
|
||||
|
||||
// Update custom style for admin area
|
||||
$this->template->set_custom_style(array(
|
||||
array(
|
||||
'name' => 'adm',
|
||||
'ext_path' => 'adm/style/',
|
||||
),
|
||||
), array($phpbb_root_path . 'adm/style'));
|
||||
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_ENABLE', time(), array($ext_name));
|
||||
}
|
||||
catch (\phpbb\db\migration\exception $e)
|
||||
{
|
||||
$this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user));
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_ext_enable';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'U_RETURN' => $this->u_action . '&action=list',
|
||||
));
|
||||
break;
|
||||
|
||||
case 'disable_pre':
|
||||
if (!$this->ext_manager->is_enabled($ext_name))
|
||||
{
|
||||
redirect($this->u_action);
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_ext_disable';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'PRE' => true,
|
||||
'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_DISABLE_CONFIRM', $md_manager->get_metadata('display-name')),
|
||||
'U_DISABLE' => $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name),
|
||||
));
|
||||
break;
|
||||
|
||||
case 'disable':
|
||||
if (!$this->ext_manager->is_enabled($ext_name))
|
||||
{
|
||||
redirect($this->u_action);
|
||||
}
|
||||
|
||||
while ($this->ext_manager->disable_step($ext_name))
|
||||
{
|
||||
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
|
||||
if ((time() - $start_time) >= $safe_time_limit)
|
||||
{
|
||||
$this->template->assign_var('S_NEXT_STEP', true);
|
||||
|
||||
meta_refresh(0, $this->u_action . '&action=disable&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('disable.' . $ext_name));
|
||||
}
|
||||
}
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_DISABLE', time(), array($ext_name));
|
||||
|
||||
$this->tpl_name = 'acp_ext_disable';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'U_RETURN' => $this->u_action . '&action=list',
|
||||
));
|
||||
break;
|
||||
|
||||
case 'delete_data_pre':
|
||||
if ($this->ext_manager->is_enabled($ext_name))
|
||||
{
|
||||
redirect($this->u_action);
|
||||
}
|
||||
$this->tpl_name = 'acp_ext_delete_data';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'PRE' => true,
|
||||
'L_CONFIRM_MESSAGE' => $this->user->lang('EXTENSION_DELETE_DATA_CONFIRM', $md_manager->get_metadata('display-name')),
|
||||
'U_PURGE' => $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name),
|
||||
));
|
||||
break;
|
||||
|
||||
case 'delete_data':
|
||||
if ($this->ext_manager->is_enabled($ext_name))
|
||||
{
|
||||
redirect($this->u_action);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
while ($this->ext_manager->purge_step($ext_name))
|
||||
{
|
||||
// Are we approaching the time limit? If so we want to pause the update and continue after refreshing
|
||||
if ((time() - $start_time) >= $safe_time_limit)
|
||||
{
|
||||
$this->template->assign_var('S_NEXT_STEP', true);
|
||||
|
||||
meta_refresh(0, $this->u_action . '&action=delete_data&ext_name=' . urlencode($ext_name) . '&hash=' . generate_link_hash('delete_data.' . $ext_name));
|
||||
}
|
||||
}
|
||||
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_EXT_PURGE', time(), array($ext_name));
|
||||
}
|
||||
catch (\phpbb\db\migration\exception $e)
|
||||
{
|
||||
$this->template->assign_var('MIGRATOR_ERROR', $e->getLocalisedMessage($this->user));
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_ext_delete_data';
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'U_RETURN' => $this->u_action . '&action=list',
|
||||
));
|
||||
break;
|
||||
|
||||
case 'details':
|
||||
// Output it to the template
|
||||
$meta = $md_manager->get_metadata('all');
|
||||
$this->output_metadata_to_template($meta);
|
||||
|
||||
if (isset($meta['extra']['version-check']))
|
||||
{
|
||||
try
|
||||
{
|
||||
$updates_available = $this->ext_manager->version_check($md_manager, $this->request->variable('versioncheck_force', false), false, $this->config['extension_force_unstable'] ? 'unstable' : null);
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'S_UP_TO_DATE' => empty($updates_available),
|
||||
'UP_TO_DATE_MSG' => $this->user->lang(empty($updates_available) ? 'UP_TO_DATE' : 'NOT_UP_TO_DATE', $md_manager->get_metadata('display-name')),
|
||||
));
|
||||
|
||||
$this->template->assign_block_vars('updates_available', $updates_available);
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'S_VERSIONCHECK_FAIL' => true,
|
||||
'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '',
|
||||
));
|
||||
}
|
||||
$this->template->assign_var('S_VERSIONCHECK', true);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->template->assign_var('S_VERSIONCHECK', false);
|
||||
}
|
||||
|
||||
$this->template->assign_vars(array(
|
||||
'U_BACK' => $this->u_action . '&action=list',
|
||||
'U_VERSIONCHECK_FORCE' => $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')),
|
||||
));
|
||||
|
||||
$this->tpl_name = 'acp_ext_details';
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Event to run after a specific action on extension has completed
|
||||
*
|
||||
* @event core.acp_extensions_run_action_after
|
||||
* @var string action Action that has run
|
||||
* @var string u_action Url we are at
|
||||
* @var string ext_name Extension name from request
|
||||
* @var int safe_time_limit Safe limit of execution time
|
||||
* @var int start_time Start time
|
||||
* @var string tpl_name Template file to load
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$u_action = $this->u_action;
|
||||
$tpl_name = $this->tpl_name;
|
||||
$vars = array('action', 'u_action', 'ext_name', 'safe_time_limit', 'start_time', 'tpl_name');
|
||||
extract($this->phpbb_dispatcher->trigger_event('core.acp_extensions_run_action_after', compact($vars)));
|
||||
|
||||
// In case they have been updated by the event
|
||||
$this->u_action = $u_action;
|
||||
$this->tpl_name = $tpl_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the enabled extensions and dumps to the template
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function list_enabled_exts()
|
||||
{
|
||||
$enabled_extension_meta_data = array();
|
||||
|
||||
foreach ($this->ext_manager->all_enabled() as $name => $location)
|
||||
{
|
||||
$md_manager = $this->ext_manager->create_extension_metadata_manager($name);
|
||||
|
||||
try
|
||||
{
|
||||
$meta = $md_manager->get_metadata('all');
|
||||
$enabled_extension_meta_data[$name] = array(
|
||||
'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
|
||||
'META_VERSION' => $meta['version'],
|
||||
);
|
||||
|
||||
if (isset($meta['extra']['version-check']))
|
||||
{
|
||||
try
|
||||
{
|
||||
$force_update = $this->request->variable('versioncheck_force', false);
|
||||
$updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update);
|
||||
|
||||
$enabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates);
|
||||
$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true;
|
||||
$enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name'));
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
// Ignore exceptions due to the version check
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
|
||||
'S_VERSIONCHECK' => false,
|
||||
));
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
{
|
||||
$enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
uasort($enabled_extension_meta_data, array($this, 'sort_extension_meta_data_table'));
|
||||
|
||||
foreach ($enabled_extension_meta_data as $name => $block_vars)
|
||||
{
|
||||
$block_vars['NAME'] = $name;
|
||||
$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name);
|
||||
|
||||
$this->template->assign_block_vars('enabled', $block_vars);
|
||||
|
||||
$this->output_actions('enabled', array(
|
||||
'DISABLE' => $this->u_action . '&action=disable_pre&ext_name=' . urlencode($name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the disabled extensions and dumps to the template
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function list_disabled_exts()
|
||||
{
|
||||
$disabled_extension_meta_data = array();
|
||||
|
||||
foreach ($this->ext_manager->all_disabled() as $name => $location)
|
||||
{
|
||||
$md_manager = $this->ext_manager->create_extension_metadata_manager($name);
|
||||
|
||||
try
|
||||
{
|
||||
$meta = $md_manager->get_metadata('all');
|
||||
$disabled_extension_meta_data[$name] = array(
|
||||
'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
|
||||
'META_VERSION' => $meta['version'],
|
||||
);
|
||||
|
||||
if (isset($meta['extra']['version-check']))
|
||||
{
|
||||
$force_update = $this->request->variable('versioncheck_force', false);
|
||||
$updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update);
|
||||
|
||||
$disabled_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates);
|
||||
$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true;
|
||||
$disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
catch (version_check_exception $e)
|
||||
{
|
||||
$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
|
||||
'S_VERSIONCHECK' => false,
|
||||
));
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
{
|
||||
$disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
uasort($disabled_extension_meta_data, array($this, 'sort_extension_meta_data_table'));
|
||||
|
||||
foreach ($disabled_extension_meta_data as $name => $block_vars)
|
||||
{
|
||||
$block_vars['NAME'] = $name;
|
||||
$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name);
|
||||
|
||||
$this->template->assign_block_vars('disabled', $block_vars);
|
||||
|
||||
$this->output_actions('disabled', array(
|
||||
'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name),
|
||||
'DELETE_DATA' => $this->u_action . '&action=delete_data_pre&ext_name=' . urlencode($name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the available extensions and dumps to the template
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function list_available_exts()
|
||||
{
|
||||
$uninstalled = array_diff_key($this->ext_manager->all_available(), $this->ext_manager->all_configured());
|
||||
|
||||
$available_extension_meta_data = array();
|
||||
|
||||
foreach ($uninstalled as $name => $location)
|
||||
{
|
||||
$md_manager = $this->ext_manager->create_extension_metadata_manager($name);
|
||||
|
||||
try
|
||||
{
|
||||
$meta = $md_manager->get_metadata('all');
|
||||
$available_extension_meta_data[$name] = array(
|
||||
'META_DISPLAY_NAME' => $md_manager->get_metadata('display-name'),
|
||||
'META_VERSION' => $meta['version'],
|
||||
);
|
||||
|
||||
if (isset($meta['extra']['version-check']))
|
||||
{
|
||||
$force_update = $this->request->variable('versioncheck_force', false);
|
||||
$updates = $this->ext_manager->version_check($md_manager, $force_update, !$force_update);
|
||||
|
||||
$available_extension_meta_data[$name]['S_UP_TO_DATE'] = empty($updates);
|
||||
$available_extension_meta_data[$name]['S_VERSIONCHECK'] = true;
|
||||
$available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$available_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
}
|
||||
catch (version_check_exception $e)
|
||||
{
|
||||
$available_extension_meta_data[$name]['S_VERSIONCHECK'] = false;
|
||||
}
|
||||
catch (exception_interface $e)
|
||||
{
|
||||
$message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$this->template->assign_block_vars('disabled', array(
|
||||
'META_DISPLAY_NAME' => $this->user->lang('EXTENSION_INVALID_LIST', $name, $message),
|
||||
'S_VERSIONCHECK' => false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
uasort($available_extension_meta_data, array($this, 'sort_extension_meta_data_table'));
|
||||
|
||||
foreach ($available_extension_meta_data as $name => $block_vars)
|
||||
{
|
||||
$block_vars['NAME'] = $name;
|
||||
$block_vars['U_DETAILS'] = $this->u_action . '&action=details&ext_name=' . urlencode($name);
|
||||
|
||||
$this->template->assign_block_vars('disabled', $block_vars);
|
||||
|
||||
$this->output_actions('disabled', array(
|
||||
'ENABLE' => $this->u_action . '&action=enable_pre&ext_name=' . urlencode($name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output actions to a block
|
||||
*
|
||||
* @param string $block
|
||||
* @param array $actions
|
||||
*/
|
||||
private function output_actions($block, $actions)
|
||||
{
|
||||
foreach ($actions as $lang => $url)
|
||||
{
|
||||
$this->template->assign_block_vars($block . '.actions', array(
|
||||
'L_ACTION' => $this->user->lang('EXTENSION_' . $lang),
|
||||
'L_ACTION_EXPLAIN' => (isset($this->user->lang['EXTENSION_' . $lang . '_EXPLAIN'])) ? $this->user->lang('EXTENSION_' . $lang . '_EXPLAIN') : '',
|
||||
'U_ACTION' => $url,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort helper for the table containing the metadata about the extensions.
|
||||
*/
|
||||
protected function sort_extension_meta_data_table($val1, $val2)
|
||||
{
|
||||
return strnatcasecmp($val1['META_DISPLAY_NAME'], $val2['META_DISPLAY_NAME']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs extension metadata into the template
|
||||
*
|
||||
* @param array $metadata Array with all metadata for the extension
|
||||
* @return null
|
||||
*/
|
||||
public function output_metadata_to_template($metadata)
|
||||
{
|
||||
$this->template->assign_vars(array(
|
||||
'META_NAME' => $metadata['name'],
|
||||
'META_TYPE' => $metadata['type'],
|
||||
'META_DESCRIPTION' => (isset($metadata['description'])) ? $metadata['description'] : '',
|
||||
'META_HOMEPAGE' => (isset($metadata['homepage'])) ? $metadata['homepage'] : '',
|
||||
'META_VERSION' => $metadata['version'],
|
||||
'META_TIME' => (isset($metadata['time'])) ? $metadata['time'] : '',
|
||||
'META_LICENSE' => $metadata['license'],
|
||||
|
||||
'META_REQUIRE_PHP' => (isset($metadata['require']['php'])) ? $metadata['require']['php'] : '',
|
||||
'META_REQUIRE_PHP_FAIL' => (isset($metadata['require']['php'])) ? false : true,
|
||||
|
||||
'META_REQUIRE_PHPBB' => (isset($metadata['extra']['soft-require']['phpbb/phpbb'])) ? $metadata['extra']['soft-require']['phpbb/phpbb'] : '',
|
||||
'META_REQUIRE_PHPBB_FAIL' => (isset($metadata['extra']['soft-require']['phpbb/phpbb'])) ? false : true,
|
||||
|
||||
'META_DISPLAY_NAME' => (isset($metadata['extra']['display-name'])) ? $metadata['extra']['display-name'] : '',
|
||||
));
|
||||
|
||||
foreach ($metadata['authors'] as $author)
|
||||
{
|
||||
$this->template->assign_block_vars('meta_authors', array(
|
||||
'AUTHOR_NAME' => $author['name'],
|
||||
'AUTHOR_EMAIL' => (isset($author['email'])) ? $author['email'] : '',
|
||||
'AUTHOR_HOMEPAGE' => (isset($author['homepage'])) ? $author['homepage'] : '',
|
||||
'AUTHOR_ROLE' => (isset($author['role'])) ? $author['role'] : '',
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
2179
includes/acp/acp_forums.php
Normal file
2179
includes/acp/acp_forums.php
Normal file
File diff suppressed because it is too large
Load Diff
1228
includes/acp/acp_groups.php
Normal file
1228
includes/acp/acp_groups.php
Normal file
File diff suppressed because it is too large
Load Diff
143
includes/acp/acp_help_phpbb.php
Normal file
143
includes/acp/acp_help_phpbb.php
Normal file
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_help_phpbb
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $config, $request, $template, $user, $phpbb_dispatcher, $phpbb_admin_path, $phpbb_root_path, $phpEx;
|
||||
|
||||
if (!class_exists('phpbb_questionnaire_data_collector'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/questionnaire/questionnaire.' . $phpEx);
|
||||
}
|
||||
|
||||
$collect_url = "https://www.phpbb.com/stats/receive_stats.php";
|
||||
|
||||
$this->tpl_name = 'acp_help_phpbb';
|
||||
$this->page_title = 'ACP_HELP_PHPBB';
|
||||
|
||||
$submit = ($request->is_set_post('submit')) ? true : false;
|
||||
|
||||
$form_key = 'acp_help_phpbb';
|
||||
add_form_key($form_key);
|
||||
$error = array();
|
||||
|
||||
if ($submit && !check_form_key($form_key))
|
||||
{
|
||||
$error[] = $user->lang['FORM_INVALID'];
|
||||
}
|
||||
// Do not write values if there is an error
|
||||
if (count($error))
|
||||
{
|
||||
$submit = false;
|
||||
}
|
||||
|
||||
// generate a unique id if necessary
|
||||
if (!isset($config['questionnaire_unique_id']))
|
||||
{
|
||||
$install_id = unique_id();
|
||||
$config->set('questionnaire_unique_id', $install_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
$install_id = $config['questionnaire_unique_id'];
|
||||
}
|
||||
|
||||
$collector = new phpbb_questionnaire_data_collector($install_id);
|
||||
|
||||
// Add data provider
|
||||
$collector->add_data_provider(new phpbb_questionnaire_php_data_provider());
|
||||
$collector->add_data_provider(new phpbb_questionnaire_system_data_provider());
|
||||
$collector->add_data_provider(new phpbb_questionnaire_phpbb_data_provider($config));
|
||||
|
||||
/**
|
||||
* Event to modify ACP help phpBB page and/or listen to submit
|
||||
*
|
||||
* @event core.acp_help_phpbb_submit_before
|
||||
* @var boolean submit Do we display the form or process the submission
|
||||
* @since 3.2.0-RC2
|
||||
*/
|
||||
$vars = array('submit');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_help_phpbb_submit_before', compact($vars)));
|
||||
|
||||
if ($submit)
|
||||
{
|
||||
$config->set('help_send_statistics', $request->variable('help_send_statistics', false));
|
||||
$response = $request->variable('send_statistics_response', '');
|
||||
|
||||
$config->set('help_send_statistics_time', time());
|
||||
|
||||
if (!empty($response))
|
||||
{
|
||||
if ((strpos($response, 'Thank you') !== false || strpos($response, 'Flood protection') !== false))
|
||||
{
|
||||
trigger_error($user->lang('THANKS_SEND_STATISTICS') . adm_back_link($this->u_action));
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error($user->lang('FAIL_SEND_STATISTICS') . adm_back_link($this->u_action));
|
||||
}
|
||||
}
|
||||
|
||||
trigger_error($user->lang('CONFIG_UPDATED') . adm_back_link($this->u_action));
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'U_COLLECT_STATS' => $collect_url,
|
||||
'S_COLLECT_STATS' => (!empty($config['help_send_statistics'])) ? true : false,
|
||||
'RAW_DATA' => $collector->get_data_for_form(),
|
||||
'U_ACP_MAIN' => append_sid("{$phpbb_admin_path}index.$phpEx"),
|
||||
'U_ACTION' => $this->u_action,
|
||||
// Pass earliest time we should try to send stats again
|
||||
'COLLECT_STATS_TIME' => intval($config['help_send_statistics_time']) + 86400,
|
||||
));
|
||||
|
||||
$raw = $collector->get_data_raw();
|
||||
|
||||
foreach ($raw as $provider => $data)
|
||||
{
|
||||
if ($provider == 'install_id')
|
||||
{
|
||||
$data = array($provider => $data);
|
||||
}
|
||||
|
||||
$template->assign_block_vars('providers', array(
|
||||
'NAME' => htmlspecialchars($provider),
|
||||
));
|
||||
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
if (is_array($value))
|
||||
{
|
||||
$value = utf8_wordwrap(serialize($value), 75, "\n", true);
|
||||
}
|
||||
|
||||
$template->assign_block_vars('providers.values', array(
|
||||
'KEY' => utf8_htmlspecialchars($key),
|
||||
'VALUE' => utf8_htmlspecialchars($value),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
999
includes/acp/acp_icons.php
Normal file
999
includes/acp/acp_icons.php
Normal file
@@ -0,0 +1,999 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo [smilies] check regular expressions for special char replacements (stored specialchared in db)
|
||||
*/
|
||||
class acp_icons
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $cache;
|
||||
global $config, $phpbb_root_path;
|
||||
global $request, $phpbb_container;
|
||||
|
||||
$user->add_lang('acp/posting');
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$action = (isset($_POST['add'])) ? 'add' : $action;
|
||||
$action = (isset($_POST['edit'])) ? 'edit' : $action;
|
||||
$action = (isset($_POST['import'])) ? 'import' : $action;
|
||||
$icon_id = $request->variable('id', 0);
|
||||
$submit = $request->is_set_post('submit', false);
|
||||
|
||||
$form_key = 'acp_icons';
|
||||
add_form_key($form_key);
|
||||
|
||||
$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;
|
||||
}
|
||||
|
||||
// adjust the width and height to be lower than 128px while perserving the aspect ratio (for icons)
|
||||
if ($mode == 'icons')
|
||||
{
|
||||
if ($img_size[0] > 127 && $img_size[0] > $img_size[1])
|
||||
{
|
||||
$img_size[1] = (int) ($img_size[1] * (127 / $img_size[0]));
|
||||
$img_size[0] = 127;
|
||||
}
|
||||
else if ($img_size[1] > 127)
|
||||
{
|
||||
$img_size[0] = (int) ($img_size[0] * (127 / $img_size[1]));
|
||||
$img_size[1] = 127;
|
||||
}
|
||||
}
|
||||
|
||||
$_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 (count($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;
|
||||
$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;
|
||||
$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 : 6);
|
||||
$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'],
|
||||
'TEXT_ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : $img,
|
||||
'ALT' => ($mode == 'icons' && !empty($img_row['icons_alt'])) ? $img_row['icons_alt'] : '',
|
||||
'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' && count($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,
|
||||
|
||||
'CODE' => $default_row['code'],
|
||||
'EMOTION' => $default_row['emotion'],
|
||||
|
||||
'WIDTH' => $default_row['smiley_width'],
|
||||
'HEIGHT' => $default_row['smiley_height'],
|
||||
));
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case 'create':
|
||||
case 'modify':
|
||||
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
// Get items to create/modify
|
||||
$images = (isset($_POST['image'])) ? array_keys($request->variable('image', array('' => 0))) : array();
|
||||
|
||||
// Now really get the items
|
||||
$image_id = (isset($_POST['id'])) ? $request->variable('id', array('' => 0)) : array();
|
||||
$image_order = (isset($_POST['order'])) ? $request->variable('order', array('' => 0)) : array();
|
||||
$image_width = (isset($_POST['width'])) ? $request->variable('width', array('' => 0)) : array();
|
||||
$image_height = (isset($_POST['height'])) ? $request->variable('height', array('' => 0)) : array();
|
||||
$image_add = (isset($_POST['add_img'])) ? $request->variable('add_img', array('' => 0)) : array();
|
||||
$image_emotion = $request->variable('emotion', array('' => ''), true);
|
||||
$image_code = $request->variable('code', array('' => ''), true);
|
||||
$image_alt = ($request->is_set_post('alt')) ? $request->variable('alt', array('' => ''), true) : array();
|
||||
$image_display_on_posting = (isset($_POST['display_on_posting'])) ? $request->variable('display_on_posting', array('' => 0)) : array();
|
||||
|
||||
// Ok, add the relevant bits if we are adding new codes to existing emoticons...
|
||||
if ($request->variable('add_additional_code', false, false, \phpbb\request\request_interface::POST))
|
||||
{
|
||||
$add_image = $request->variable('add_image', '');
|
||||
$add_code = $request->variable('add_code', '', true);
|
||||
$add_emotion = $request->variable('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->variable('add_width', 0);
|
||||
$image_height[$add_image] = $request->variable('add_height', 0);
|
||||
|
||||
if ($request->variable('add_display_on_posting', false, false, \phpbb\request\request_interface::POST))
|
||||
{
|
||||
$image_display_on_posting[$add_image] = 1;
|
||||
}
|
||||
|
||||
$image_order[$add_image] = $request->variable('add_order', 0);
|
||||
}
|
||||
}
|
||||
|
||||
if ($mode == 'smilies' && $action == 'create')
|
||||
{
|
||||
$smiley_count = $this->item_count($table);
|
||||
|
||||
$addable_smileys_count = count($images);
|
||||
foreach ($images as $image)
|
||||
{
|
||||
if (!isset($image_add[$image]))
|
||||
{
|
||||
--$addable_smileys_count;
|
||||
}
|
||||
}
|
||||
|
||||
if ($smiley_count + $addable_smileys_count > SMILEY_LIMIT)
|
||||
{
|
||||
trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
$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 (!file_exists($phpbb_root_path . $img_path . '/' . $image))
|
||||
{
|
||||
$errors[$image] = 'SMILIE_NO_FILE';
|
||||
}
|
||||
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];
|
||||
}
|
||||
|
||||
// Adjust image width/height for icons
|
||||
if ($mode == 'icons')
|
||||
{
|
||||
if ($image_width[$image] > 127 && $image_width[$image] > $image_height[$image])
|
||||
{
|
||||
$image_height[$image] = (int) ($image_height[$image] * (127 / $image_width[$image]));
|
||||
$image_width[$image] = 127;
|
||||
}
|
||||
else if ($image_height[$image] > 127)
|
||||
{
|
||||
$image_width[$image] = (int) ($image_width[$image] * (127 / $image_height[$image]));
|
||||
$image_height[$image] = 127;
|
||||
}
|
||||
}
|
||||
|
||||
$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])
|
||||
);
|
||||
}
|
||||
|
||||
if ($mode == 'icons')
|
||||
{
|
||||
$img_sql = array_merge($img_sql, array(
|
||||
'icons_alt' => $image_alt[$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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
$level = ($icons_updated) ? E_USER_NOTICE : E_USER_WARNING;
|
||||
$errormsgs = '';
|
||||
foreach ($errors as $img => $error)
|
||||
{
|
||||
$errormsgs .= '<br />' . sprintf($user->lang[$error], $img);
|
||||
}
|
||||
if ($action == 'modify')
|
||||
{
|
||||
trigger_error($user->lang($lang . '_EDITED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error($user->lang($lang . '_ADDED', $icons_updated) . $errormsgs . adm_back_link($this->u_action), $level);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'import':
|
||||
|
||||
$pak = $request->variable('pak', '');
|
||||
$current = $request->variable('current', '');
|
||||
|
||||
if ($pak != '')
|
||||
{
|
||||
$order = 0;
|
||||
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
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 ((count($data[1]) != 4 && $mode == 'icons') ||
|
||||
((count($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')
|
||||
{
|
||||
switch ($db->get_sql_layer())
|
||||
{
|
||||
case 'sqlite3':
|
||||
$db->sql_query('DELETE FROM ' . $table);
|
||||
break;
|
||||
|
||||
default:
|
||||
$db->sql_query('TRUNCATE TABLE ' . $table);
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if ($mode == 'smilies')
|
||||
{
|
||||
$smiley_count = $this->item_count($table);
|
||||
if ($smiley_count + count($pak_ary) > SMILEY_LIMIT)
|
||||
{
|
||||
trigger_error($user->lang('TOO_MANY_SMILIES', SMILEY_LIMIT) . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pak_ary as $pak_entry)
|
||||
{
|
||||
$data = array();
|
||||
if (preg_match_all("#'(.*?)', ?#", $pak_entry, $data))
|
||||
{
|
||||
if ((count($data[1]) != 4 && $mode == 'icons') ||
|
||||
(count($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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
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&hash=' . generate_link_hash('acp_icons') . '">', '</a>'),
|
||||
|
||||
'S_USER_NOTICE' => true,
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
|
||||
case 'send':
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_icons'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$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('Cache-Control: 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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'MESSAGE_TITLE' => $user->lang['INFORMATION'],
|
||||
'MESSAGE_TEXT' => $notice,
|
||||
'REFRESH_DATA' => array(
|
||||
'time' => 3
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
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':
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_icons'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
// 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);
|
||||
$move_executed = (bool) $db->sql_affectedrows();
|
||||
|
||||
// Only update the other entry too if the previous entry got updated
|
||||
if ($move_executed)
|
||||
{
|
||||
$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);
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'success' => $move_executed,
|
||||
));
|
||||
}
|
||||
|
||||
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',
|
||||
)
|
||||
);
|
||||
|
||||
/* @var $pagination \phpbb\pagination */
|
||||
$pagination = $phpbb_container->get('pagination');
|
||||
$pagination_start = $request->variable('start', 0);
|
||||
$spacer = false;
|
||||
|
||||
$item_count = $this->item_count($table);
|
||||
|
||||
$sql = "SELECT *
|
||||
FROM $table
|
||||
ORDER BY {$fields}_order ASC";
|
||||
$result = $db->sql_query_limit($sql, $config['smilies_per_page'], $pagination_start);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$alt_text = ($mode == 'smilies') ? $row['code'] : (($mode == 'icons' && !empty($row['icons_alt'])) ? $row['icons_alt'] : $row['icons_url']);
|
||||
|
||||
$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'] . '&start=' . $pagination_start . '&hash=' . generate_link_hash('acp_icons'),
|
||||
'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row[$fields . '_id'] . '&start=' . $pagination_start . '&hash=' . generate_link_hash('acp_icons'),
|
||||
));
|
||||
|
||||
if (!$spacer && !$row['display_on_posting'])
|
||||
{
|
||||
$spacer = true;
|
||||
}
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$pagination->generate_template_pagination($this->u_action, 'pagination', 'start', $item_count, $config['smilies_per_page'], $pagination_start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the count of smilies or icons in the database
|
||||
*
|
||||
* @param string $table The table of items to count.
|
||||
* @return int number of items
|
||||
*/
|
||||
/* private */ function item_count($table)
|
||||
{
|
||||
global $db;
|
||||
|
||||
$sql = "SELECT COUNT(*) AS item_count
|
||||
FROM $table";
|
||||
$result = $db->sql_query($sql);
|
||||
$item_count = (int) $db->sql_fetchfield('item_count');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $item_count;
|
||||
}
|
||||
}
|
||||
322
includes/acp/acp_inactive.php
Normal file
322
includes/acp/acp_inactive.php
Normal file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
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, $phpbb_container, $phpbb_log, $request;
|
||||
global $phpbb_root_path, $phpbb_admin_path, $phpEx;
|
||||
|
||||
if (!function_exists('user_active_flip'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
$user->add_lang('memberlist');
|
||||
|
||||
$action = $request->variable('action', '');
|
||||
$mark = (isset($_REQUEST['mark'])) ? $request->variable('mark', array(0)) : array();
|
||||
$start = $request->variable('start', 0);
|
||||
$submit = isset($_POST['submit']);
|
||||
|
||||
// Sort keys
|
||||
$sort_days = $request->variable('st', 0);
|
||||
$sort_key = $request->variable('sk', 'i');
|
||||
$sort_dir = $request->variable('sd', 'd');
|
||||
|
||||
$form_key = 'acp_inactive';
|
||||
add_form_key($form_key);
|
||||
|
||||
/* @var $pagination \phpbb\pagination */
|
||||
$pagination = $phpbb_container->get('pagination');
|
||||
|
||||
// We build the sort key and per page settings here, because they may be needed later
|
||||
|
||||
// Number of entries to display
|
||||
$per_page = $request->variable('users_per_page', (int) $config['topics_per_page']);
|
||||
|
||||
// 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'], 'd' => $user->lang['SORT_LAST_REMINDER'], 'r' => $user->lang['SORT_REASON'], 'u' => $user->lang['SORT_USERNAME'], 'p' => $user->lang['SORT_POSTS'], 'e' => $user->lang['SORT_REMINDER']);
|
||||
$sort_by_sql = array('i' => 'user_inactive_time', 'j' => 'user_regdate', 'l' => 'user_lastvisit', 'd' => 'user_reminded_time', 'r' => 'user_inactive_reason', 'u' => 'username_clean', 'p' => 'user_posts', 'e' => 'user_reminded');
|
||||
|
||||
$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);
|
||||
|
||||
if ($submit && count($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')
|
||||
{
|
||||
// Get those 'being activated'...
|
||||
$sql = 'SELECT user_id, username' . (($config['require_activation'] == USER_ACTIVATION_ADMIN) ? ', 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))
|
||||
{
|
||||
if (!class_exists('messenger'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
|
||||
}
|
||||
|
||||
$messenger = new messenger(false);
|
||||
|
||||
foreach ($inactive_users as $row)
|
||||
{
|
||||
$messenger->template('admin_welcome_activated', $row['user_lang']);
|
||||
|
||||
$messenger->set_addresses($row);
|
||||
|
||||
$messenger->anti_abuse_headers($config, $user);
|
||||
|
||||
$messenger->assign_vars(array(
|
||||
'USERNAME' => htmlspecialchars_decode($row['username']))
|
||||
);
|
||||
|
||||
$messenger->send(NOTIFY_EMAIL);
|
||||
}
|
||||
|
||||
$messenger->save_queue();
|
||||
}
|
||||
|
||||
if (!empty($inactive_users))
|
||||
{
|
||||
foreach ($inactive_users as $row)
|
||||
{
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE', false, array($row['username']));
|
||||
$phpbb_log->add('user', $user->data['user_id'], $user->ip, 'LOG_USER_ACTIVE_USER', false, array(
|
||||
'reportee_id' => $row['user_id']
|
||||
));
|
||||
}
|
||||
|
||||
trigger_error(sprintf($user->lang['LOG_INACTIVE_ACTIVATE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
|
||||
}
|
||||
|
||||
// For activate we really need to redirect, else a refresh can result in users being deactivated again
|
||||
$u_action = $this->u_action . "&$u_sort_param&start=$start";
|
||||
$u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : '';
|
||||
|
||||
redirect($u_action);
|
||||
}
|
||||
else if ($action == 'delete')
|
||||
{
|
||||
if (confirm_box(true))
|
||||
{
|
||||
if (!$auth->acl_get('a_userdel'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
user_delete('retain', $mark, true);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_' . strtoupper($action), false, array(implode(', ', $user_affected)));
|
||||
|
||||
trigger_error(sprintf($user->lang['LOG_INACTIVE_DELETE'], implode($user->lang['COMMA_SEPARATOR'], $user_affected) . ' ' . adm_back_link($this->u_action)));
|
||||
}
|
||||
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) . '
|
||||
AND user_inactive_reason';
|
||||
|
||||
$sql .= ($config['require_activation'] == USER_ACTIVATION_ADMIN) ? ' = ' . INACTIVE_REMIND : ' <> ' . INACTIVE_MANUAL;
|
||||
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
if ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
// Send the messages
|
||||
if (!class_exists('messenger'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_messenger.' . $phpEx);
|
||||
}
|
||||
|
||||
$messenger = new messenger();
|
||||
$usernames = $user_ids = array();
|
||||
|
||||
do
|
||||
{
|
||||
$messenger->template('user_remind_inactive', $row['user_lang']);
|
||||
|
||||
$messenger->set_addresses($row);
|
||||
|
||||
$messenger->anti_abuse_headers($config, $user);
|
||||
|
||||
$messenger->assign_vars(array(
|
||||
'USERNAME' => htmlspecialchars_decode($row['username']),
|
||||
'REGISTER_DATE' => $user->format_date($row['user_regdate'], false, true),
|
||||
'U_ACTIVATE' => generate_board_url() . "/ucp.$phpEx?mode=activate&u=" . $row['user_id'] . '&k=' . $row['user_actkey'])
|
||||
);
|
||||
|
||||
$messenger->send($row['user_notify_type']);
|
||||
|
||||
$usernames[] = $row['username'];
|
||||
$user_ids[] = (int) $row['user_id'];
|
||||
}
|
||||
while ($row = $db->sql_fetchrow($result));
|
||||
|
||||
$messenger->save_queue();
|
||||
|
||||
// Add the remind state to the database
|
||||
$sql = 'UPDATE ' . USERS_TABLE . '
|
||||
SET user_reminded = user_reminded + 1,
|
||||
user_reminded_time = ' . time() . '
|
||||
WHERE ' . $db->sql_in_set('user_id', $user_ids);
|
||||
$db->sql_query($sql);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_INACTIVE_REMIND', false, array(implode(', ', $usernames)));
|
||||
|
||||
trigger_error(sprintf($user->lang['LOG_INACTIVE_REMIND'], implode($user->lang['COMMA_SEPARATOR'], $usernames) . ' ' . adm_back_link($this->u_action)));
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// For remind we really need to redirect, else a refresh can result in more than one reminder
|
||||
$u_action = $this->u_action . "&$u_sort_param&start=$start";
|
||||
$u_action .= ($per_page != $config['topics_per_page']) ? "&users_per_page=$per_page" : '';
|
||||
|
||||
redirect($u_action);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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, $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']),
|
||||
'REMINDED_DATE' => $user->format_date($row['user_reminded_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'],
|
||||
'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
|
||||
'REMINDED' => $row['user_reminded'],
|
||||
|
||||
'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
|
||||
|
||||
'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview&redirect=acp_inactive')),
|
||||
'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
|
||||
'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
|
||||
'USER_EMAIL' => $row['user_email'],
|
||||
|
||||
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"),
|
||||
'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '',
|
||||
));
|
||||
}
|
||||
|
||||
$option_ary = array('activate' => 'ACTIVATE', 'delete' => 'DELETE');
|
||||
if ($config['email_enable'])
|
||||
{
|
||||
$option_ary += array('remind' => 'REMIND');
|
||||
}
|
||||
|
||||
$base_url = $this->u_action . "&$u_sort_param&users_per_page=$per_page";
|
||||
$pagination->generate_template_pagination($base_url, 'pagination', 'start', $inactive_count, $per_page, $start);
|
||||
|
||||
$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,
|
||||
'USERS_PER_PAGE' => $per_page,
|
||||
|
||||
'U_ACTION' => $this->u_action . "&$u_sort_param&users_per_page=$per_page&start=$start",
|
||||
));
|
||||
|
||||
$this->tpl_name = 'acp_inactive';
|
||||
$this->page_title = 'ACP_INACTIVE_USERS';
|
||||
}
|
||||
}
|
||||
144
includes/acp/acp_jabber.php
Normal file
144
includes/acp/acp_jabber.php
Normal file
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @todo Check/enter/update transport info
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_jabber
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $phpbb_log, $request;
|
||||
global $config, $phpbb_root_path, $phpEx;
|
||||
|
||||
$user->add_lang('acp/board');
|
||||
|
||||
if (!class_exists('jabber'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_jabber.' . $phpEx);
|
||||
}
|
||||
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
|
||||
if ($mode != 'settings')
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_jabber';
|
||||
$this->page_title = 'ACP_JABBER_SETTINGS';
|
||||
|
||||
$jab_enable = $request->variable('jab_enable', (bool) $config['jab_enable']);
|
||||
$jab_host = $request->variable('jab_host', (string) $config['jab_host']);
|
||||
$jab_port = $request->variable('jab_port', (int) $config['jab_port']);
|
||||
$jab_username = $request->variable('jab_username', (string) $config['jab_username']);
|
||||
$jab_password = $request->variable('jab_password', (string) $config['jab_password']);
|
||||
$jab_package_size = $request->variable('jab_package_size', (int) $config['jab_package_size']);
|
||||
$jab_use_ssl = $request->variable('jab_use_ssl', (bool) $config['jab_use_ssl']);
|
||||
$jab_verify_peer = $request->variable('jab_verify_peer', (bool) $config['jab_verify_peer']);
|
||||
$jab_verify_peer_name = $request->variable('jab_verify_peer_name', (bool) $config['jab_verify_peer_name']);
|
||||
$jab_allow_self_signed = $request->variable('jab_allow_self_signed', (bool) $config['jab_allow_self_signed']);
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
$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, $jab_verify_peer, $jab_verify_peer_name, $jab_allow_self_signed);
|
||||
|
||||
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
|
||||
// We set this to both because users still have their jabber address entered and may want to receive jabber notifications again once it is re-enabled.
|
||||
$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);
|
||||
}
|
||||
|
||||
$config->set('jab_enable', $jab_enable);
|
||||
$config->set('jab_host', $jab_host);
|
||||
$config->set('jab_port', $jab_port);
|
||||
$config->set('jab_username', $jab_username);
|
||||
if ($jab_password !== '********')
|
||||
{
|
||||
$config->set('jab_password', $jab_password);
|
||||
}
|
||||
$config->set('jab_package_size', $jab_package_size);
|
||||
$config->set('jab_use_ssl', $jab_use_ssl);
|
||||
$config->set('jab_verify_peer', $jab_verify_peer);
|
||||
$config->set('jab_verify_peer_name', $jab_verify_peer_name);
|
||||
$config->set('jab_allow_self_signed', $jab_allow_self_signed);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, '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_port : '',
|
||||
'JAB_USERNAME' => $jab_username,
|
||||
'JAB_PASSWORD' => $jab_password !== '' ? '********' : '',
|
||||
'JAB_PACKAGE_SIZE' => $jab_package_size,
|
||||
'JAB_USE_SSL' => $jab_use_ssl,
|
||||
'JAB_VERIFY_PEER' => $jab_verify_peer,
|
||||
'JAB_VERIFY_PEER_NAME' => $jab_verify_peer_name,
|
||||
'JAB_ALLOW_SELF_SIGNED' => $jab_allow_self_signed,
|
||||
'S_CAN_USE_SSL' => jabber::can_use_ssl(),
|
||||
'S_GTALK_NOTE' => (!@function_exists('dns_get_record')) ? true : false,
|
||||
));
|
||||
}
|
||||
}
|
||||
461
includes/acp/acp_language.php
Normal file
461
includes/acp/acp_language.php
Normal file
@@ -0,0 +1,461 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
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, $template, $phpbb_log, $phpbb_container;
|
||||
global $phpbb_root_path, $phpEx, $request, $phpbb_dispatcher;
|
||||
|
||||
if (!function_exists('validate_language_iso_name'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
// Check and set some common vars
|
||||
$action = (isset($_POST['update_details'])) ? 'update_details' : '';
|
||||
$action = (isset($_POST['remove_store'])) ? 'details' : $action;
|
||||
|
||||
$submit = (empty($action) && !isset($_POST['update']) && !isset($_POST['test_connection'])) ? false : true;
|
||||
$action = (empty($action)) ? $request->variable('action', '') : $action;
|
||||
|
||||
$form_name = 'acp_lang';
|
||||
add_form_key('acp_lang');
|
||||
|
||||
$lang_id = $request->variable('id', 0);
|
||||
|
||||
$selected_lang_file = $request->variable('language_file', '|common.' . $phpEx);
|
||||
|
||||
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';
|
||||
|
||||
switch ($action)
|
||||
{
|
||||
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->variable('lang_english_name', $row['lang_english_name']),
|
||||
'lang_local_name' => $request->variable('lang_local_name', $row['lang_local_name'], true),
|
||||
'lang_author' => $request->variable('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);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_UPDATED', false, array($sql_ary['lang_english_name']));
|
||||
|
||||
trigger_error($user->lang['LANGUAGE_DETAILS_UPDATED'] . adm_back_link($this->u_action));
|
||||
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);
|
||||
|
||||
if (!$lang_entries)
|
||||
{
|
||||
trigger_error($user->lang['LANGUAGE_PACK_NOT_EXIST'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$lang_iso = $lang_entries['lang_iso'];
|
||||
|
||||
$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_iso,
|
||||
'LANG_AUTHOR' => $lang_entries['lang_author'],
|
||||
'L_MISSING_FILES' => $user->lang('THOSE_MISSING_LANG_FILES', $lang_entries['lang_local_name']),
|
||||
'L_MISSING_VARS_EXPLAIN' => $user->lang('THOSE_MISSING_LANG_VARIABLES', $lang_entries['lang_local_name']),
|
||||
));
|
||||
|
||||
// If current lang is different from the default lang, then highlight missing files and variables
|
||||
if ($lang_iso != $config['default_lang'])
|
||||
{
|
||||
try
|
||||
{
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \phpbb\recursive_dot_prefix_filter_iterator(
|
||||
new \RecursiveDirectoryIterator(
|
||||
$phpbb_root_path . 'language/' . $config['default_lang'] . '/',
|
||||
\FilesystemIterator::SKIP_DOTS
|
||||
)
|
||||
),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
foreach ($iterator as $file_info)
|
||||
{
|
||||
/** @var \RecursiveDirectoryIterator $file_info */
|
||||
$relative_path = $iterator->getInnerIterator()->getSubPathname();
|
||||
$relative_path = str_replace(DIRECTORY_SEPARATOR, '/', $relative_path);
|
||||
|
||||
if (file_exists($phpbb_root_path . 'language/' . $lang_iso . '/' . $relative_path))
|
||||
{
|
||||
if (substr($relative_path, 0 - strlen($phpEx)) === $phpEx)
|
||||
{
|
||||
$missing_vars = $this->compare_language_files($config['default_lang'], $lang_iso, $relative_path);
|
||||
|
||||
if (!empty($missing_vars))
|
||||
{
|
||||
$template->assign_block_vars('missing_varfile', array(
|
||||
'FILE_NAME' => $relative_path,
|
||||
));
|
||||
|
||||
foreach ($missing_vars as $var)
|
||||
{
|
||||
$template->assign_block_vars('missing_varfile.variable', array(
|
||||
'VAR_NAME' => $var,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$template->assign_block_vars('missing_files', array(
|
||||
'FILE_NAME' => $relative_path,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
if (confirm_box(true))
|
||||
{
|
||||
$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);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_DELETED', false, array($row['lang_english_name']));
|
||||
|
||||
$delete_message = sprintf($user->lang['LANGUAGE_PACK_DELETED'], $row['lang_english_name']);
|
||||
$lang_iso = $row['lang_iso'];
|
||||
/**
|
||||
* Run code after language deleted
|
||||
*
|
||||
* @event core.acp_language_after_delete
|
||||
* @var string lang_iso Language ISO code
|
||||
* @var string delete_message Delete message appear to user
|
||||
* @since 3.2.2-RC1
|
||||
*/
|
||||
$vars = array('lang_iso', 'delete_message');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_language_after_delete', compact($vars)));
|
||||
|
||||
trigger_error($delete_message . adm_back_link($this->u_action));
|
||||
}
|
||||
else
|
||||
{
|
||||
$s_hidden_fields = array(
|
||||
'i' => $id,
|
||||
'mode' => $mode,
|
||||
'action' => $action,
|
||||
'id' => $lang_id,
|
||||
);
|
||||
confirm_box(false, $user->lang('DELETE_LANGUAGE_CONFIRM', $row['lang_english_name']), build_hidden_fields($s_hidden_fields));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'install':
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_language'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$lang_iso = $request->variable('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();
|
||||
|
||||
// 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);
|
||||
|
||||
// We want to notify the admin that custom profile fields need to be updated for the new language.
|
||||
$notify_cpf_update = false;
|
||||
|
||||
// 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));
|
||||
$notify_cpf_update = true;
|
||||
}
|
||||
$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));
|
||||
$notify_cpf_update = true;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_LANGUAGE_PACK_INSTALLED', false, array($lang_pack['name']));
|
||||
|
||||
$message = sprintf($user->lang['LANGUAGE_PACK_INSTALLED'], $lang_pack['name']);
|
||||
$message .= ($notify_cpf_update) ? '<br /><br />' . $user->lang['LANGUAGE_PACK_CPF_UPDATE'] : '';
|
||||
trigger_error($message . adm_back_link($this->u_action));
|
||||
|
||||
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();
|
||||
|
||||
/** @var \phpbb\language\language_file_helper $language_helper */
|
||||
$language_helper = $phpbb_container->get('language.helper.language_file');
|
||||
$iso = $language_helper->get_available_languages();
|
||||
|
||||
foreach ($iso as $lang_array)
|
||||
{
|
||||
$lang_iso = $lang_array['iso'];
|
||||
|
||||
if (!in_array($lang_iso, $installed))
|
||||
{
|
||||
$new_ary[$lang_iso] = $lang_array;
|
||||
}
|
||||
}
|
||||
|
||||
unset($installed);
|
||||
|
||||
if (count($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']) . '&hash=' . generate_link_hash('acp_language'))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
unset($new_ary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two language files
|
||||
*/
|
||||
function compare_language_files($source_lang, $dest_lang, $file)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$source_file = $phpbb_root_path . 'language/' . $source_lang . '/' . $file;
|
||||
$dest_file = $phpbb_root_path . 'language/' . $dest_lang . '/' . $file;
|
||||
|
||||
if (!file_exists($dest_file))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$lang = array();
|
||||
include($source_file);
|
||||
$lang_entry_src = $lang;
|
||||
|
||||
$lang = array();
|
||||
include($dest_file);
|
||||
$lang_entry_dst = $lang;
|
||||
|
||||
unset($lang);
|
||||
|
||||
return array_diff(array_keys($lang_entry_src), array_keys($lang_entry_dst));
|
||||
}
|
||||
}
|
||||
176
includes/acp/acp_logs.php
Normal file
176
includes/acp/acp_logs.php
Normal file
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_logs
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $user, $auth, $template, $phpbb_container;
|
||||
global $config;
|
||||
global $request;
|
||||
|
||||
$user->add_lang('mcp');
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$forum_id = $request->variable('f', 0);
|
||||
$start = $request->variable('start', 0);
|
||||
$deletemark = $request->variable('delmarked', false, false, \phpbb\request\request_interface::POST);
|
||||
$deleteall = $request->variable('delall', false, false, \phpbb\request\request_interface::POST);
|
||||
$marked = $request->variable('mark', array(0));
|
||||
|
||||
// Sort keys
|
||||
$sort_days = $request->variable('st', 0);
|
||||
$sort_key = $request->variable('sk', 't');
|
||||
$sort_dir = $request->variable('sd', 'd');
|
||||
|
||||
$this->tpl_name = 'acp_logs';
|
||||
$this->log_type = constant('LOG_' . strtoupper($mode));
|
||||
|
||||
/* @var $pagination \phpbb\pagination */
|
||||
$pagination = $phpbb_container->get('pagination');
|
||||
|
||||
// Delete entries if requested and able
|
||||
if (($deletemark || $deleteall) && $auth->acl_get('a_clearlogs'))
|
||||
{
|
||||
if (confirm_box(true))
|
||||
{
|
||||
$conditions = array();
|
||||
|
||||
if ($deletemark && count($marked))
|
||||
{
|
||||
$conditions['log_id'] = array('IN' => $marked);
|
||||
}
|
||||
|
||||
if ($deleteall)
|
||||
{
|
||||
if ($sort_days)
|
||||
{
|
||||
$conditions['log_time'] = array('>=', time() - ($sort_days * 86400));
|
||||
}
|
||||
|
||||
$keywords = $request->variable('keywords', '', true);
|
||||
$conditions['keywords'] = $keywords;
|
||||
}
|
||||
|
||||
/* @var $phpbb_log \phpbb\log\log_interface */
|
||||
$phpbb_log = $phpbb_container->get('log');
|
||||
$phpbb_log->delete($mode, $conditions);
|
||||
}
|
||||
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');
|
||||
|
||||
$keywords = $request->variable('keywords', '', true);
|
||||
$keywords_param = !empty($keywords) ? '&keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
|
||||
|
||||
$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;
|
||||
$start = view_log($mode, $log_data, $log_count, $config['topics_per_page'], $start, $forum_id, 0, 0, $sql_where, $sql_sort, $keywords);
|
||||
|
||||
$base_url = $this->u_action . "&$u_sort_param$keywords_param";
|
||||
$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, $config['topics_per_page'], $start);
|
||||
|
||||
$template->assign_vars(array(
|
||||
'L_TITLE' => $l_title,
|
||||
'L_EXPLAIN' => $l_title_explain,
|
||||
'U_ACTION' => $this->u_action . "&$u_sort_param$keywords_param&start=$start",
|
||||
|
||||
'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'),
|
||||
'S_KEYWORDS' => $keywords,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ($log_data as $row)
|
||||
{
|
||||
$data = array();
|
||||
|
||||
$checks = array('viewpost', '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' => (count($data)) ? implode(' | ', $data) : '',
|
||||
'ID' => $row['id'],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
707
includes/acp/acp_main.php
Normal file
707
includes/acp/acp_main.php
Normal file
@@ -0,0 +1,707 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_main
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $config, $db, $cache, $user, $auth, $template, $request, $phpbb_log;
|
||||
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container, $phpbb_dispatcher, $phpbb_filesystem;
|
||||
|
||||
// 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 = get_username_string('full', $user_row['user_id'], $user_row['username'], $user_row['user_colour']);
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_RESTORE_PERMISSIONS' => true,
|
||||
'U_RESTORE_PERMISSIONS' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm'),
|
||||
'PERM_FROM' => $perm_from,
|
||||
'L_PERMISSIONS_TRANSFERRED_EXPLAIN' => sprintf($user->lang['PERMISSIONS_TRANSFERRED_EXPLAIN'], $perm_from, append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=restore_perm')),
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $request->variable('action', '');
|
||||
|
||||
if ($action)
|
||||
{
|
||||
if ($action === 'admlogout')
|
||||
{
|
||||
$user->unset_admin();
|
||||
redirect(append_sid("{$phpbb_root_path}index.$phpEx"));
|
||||
}
|
||||
|
||||
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;
|
||||
case 'purge_sessions':
|
||||
$confirm = true;
|
||||
$confirm_lang = 'PURGE_SESSIONS_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'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$config->set('record_online_users', 1, false);
|
||||
$config->set('record_online_date', time(), false);
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_ONLINE');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('RESET_ONLINE_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
if (!$auth->acl_get('a_board'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
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_visibility = ' . ITEM_APPROVED;
|
||||
$result = $db->sql_query($sql);
|
||||
$config->set('num_posts', (int) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT COUNT(topic_id) AS stat
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE topic_visibility = ' . ITEM_APPROVED;
|
||||
$result = $db->sql_query($sql);
|
||||
$config->set('num_topics', (int) $db->sql_fetchfield('stat'), false);
|
||||
$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);
|
||||
$config->set('num_users', (int) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT COUNT(attach_id) as stat
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 0';
|
||||
$result = $db->sql_query($sql);
|
||||
$config->set('num_files', (int) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = 'SELECT SUM(filesize) as stat
|
||||
FROM ' . ATTACHMENTS_TABLE . '
|
||||
WHERE is_orphan = 0';
|
||||
$result = $db->sql_query($sql);
|
||||
$config->set('upload_dir_size', (float) $db->sql_fetchfield('stat'), false);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if (!function_exists('update_last_username'))
|
||||
{
|
||||
include($phpbb_root_path . "includes/functions_user.$phpEx");
|
||||
}
|
||||
update_last_username();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_STATS');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('RESYNC_STATS_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'user':
|
||||
if (!$auth->acl_get('a_board'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
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) 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);
|
||||
}
|
||||
|
||||
// Still no maximum post id? Then we are finished
|
||||
if (!$max_post_id)
|
||||
{
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, '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_visibility = ' . ITEM_APPROVED . '
|
||||
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;
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POSTCOUNTS');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('RESYNC_POSTCOUNTS_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
if (!$auth->acl_get('a_board'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$config->set('board_startdate', time() - 1);
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESET_DATE');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('RESET_DATE_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'db_track':
|
||||
switch ($db->get_sql_layer())
|
||||
{
|
||||
case 'sqlite3':
|
||||
$db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
$db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
// 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 (count($sql_ary))
|
||||
{
|
||||
$db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary);
|
||||
}
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RESYNC_POST_MARKING');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('RESYNC_POST_MARKING_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'purge_cache':
|
||||
$config->increment('assets_version', 1);
|
||||
$cache->purge();
|
||||
|
||||
// Remove old renderers from the text_formatter service. Since this
|
||||
// operation is performed after the cache is purged, there is not "current"
|
||||
// renderer and in effect all renderers will be purged
|
||||
$phpbb_container->get('text_formatter.cache')->tidy();
|
||||
|
||||
// Clear permissions
|
||||
$auth->acl_clear_prefetch();
|
||||
phpbb_cache_moderators($db, $cache, $auth);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_CACHE');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('PURGE_CACHE_SUCCESS');
|
||||
}
|
||||
break;
|
||||
|
||||
case 'purge_sessions':
|
||||
if ((int) $user->data['user_type'] !== USER_FOUNDER)
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$tables = array(CONFIRM_TABLE, SESSIONS_TABLE);
|
||||
|
||||
foreach ($tables as $table)
|
||||
{
|
||||
switch ($db->get_sql_layer())
|
||||
{
|
||||
case 'sqlite3':
|
||||
$db->sql_query("DELETE FROM $table");
|
||||
break;
|
||||
|
||||
default:
|
||||
$db->sql_query("TRUNCATE TABLE $table");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// let's restore the admin session
|
||||
$reinsert_ary = array(
|
||||
'session_id' => (string) $user->session_id,
|
||||
'session_page' => (string) substr($user->page['page'], 0, 199),
|
||||
'session_forum_id' => $user->page['forum'],
|
||||
'session_user_id' => (int) $user->data['user_id'],
|
||||
'session_start' => (int) $user->data['session_start'],
|
||||
'session_last_visit' => (int) $user->data['session_last_visit'],
|
||||
'session_time' => (int) $user->time_now,
|
||||
'session_browser' => (string) trim(substr($user->browser, 0, 149)),
|
||||
'session_forwarded_for' => (string) $user->forwarded_for,
|
||||
'session_ip' => (string) $user->ip,
|
||||
'session_autologin' => (int) $user->data['session_autologin'],
|
||||
'session_admin' => 1,
|
||||
'session_viewonline' => (int) $user->data['session_viewonline'],
|
||||
);
|
||||
|
||||
$sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . $db->sql_build_array('INSERT', $reinsert_ary);
|
||||
$db->sql_query($sql);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PURGE_SESSIONS');
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
trigger_error('PURGE_SESSIONS_SUCCESS');
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Version check
|
||||
$user->add_lang('install');
|
||||
|
||||
if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.4.0', '<'))
|
||||
{
|
||||
$template->assign_vars(array(
|
||||
'S_PHP_VERSION_OLD' => true,
|
||||
'L_PHP_VERSION_OLD' => sprintf($user->lang['PHP_VERSION_OLD'], PHP_VERSION, '5.4.0', '<a href="https://www.phpbb.com/support/docs/en/3.2/ug/quickstart/requirements">', '</a>'),
|
||||
));
|
||||
}
|
||||
|
||||
if ($auth->acl_get('a_board'))
|
||||
{
|
||||
$version_helper = $phpbb_container->get('version_helper');
|
||||
try
|
||||
{
|
||||
$recheck = $request->variable('versioncheck_force', false);
|
||||
$updates_available = $version_helper->get_update_on_branch($recheck);
|
||||
$upgrades_available = $version_helper->get_suggested_updates();
|
||||
if (!empty($upgrades_available))
|
||||
{
|
||||
$upgrades_available = array_pop($upgrades_available);
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_VERSION_UP_TO_DATE' => empty($updates_available),
|
||||
'S_VERSION_UPGRADEABLE' => !empty($upgrades_available),
|
||||
'UPGRADE_INSTRUCTIONS' => !empty($upgrades_available) ? $user->lang('UPGRADE_INSTRUCTIONS', $upgrades_available['current'], $upgrades_available['announcement']) : false,
|
||||
));
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
{
|
||||
$message = call_user_func_array(array($user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters()));
|
||||
$template->assign_vars(array(
|
||||
'S_VERSIONCHECK_FAIL' => true,
|
||||
'VERSIONCHECK_FAIL_REASON' => ($e->getMessage() !== 'VERSIONCHECK_FAIL') ? $message : '',
|
||||
));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// We set this template var to true, to not display an outdated version notice.
|
||||
$template->assign_var('S_VERSION_UP_TO_DATE', true);
|
||||
}
|
||||
|
||||
// Incomplete update?
|
||||
if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<'))
|
||||
{
|
||||
$template->assign_var('S_UPDATE_INCOMPLETE', true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notice admin
|
||||
*
|
||||
* @event core.acp_main_notice
|
||||
* @since 3.1.0-RC3
|
||||
*/
|
||||
$phpbb_dispatcher->dispatch('core.acp_main_notice');
|
||||
|
||||
// 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'] && @extension_loaded('zlib')) ? $user->lang['ON'] : $user->lang['OFF'],
|
||||
'DATABASE_INFO' => $db->sql_server_info(),
|
||||
'PHP_VERSION_INFO' => PHP_VERSION,
|
||||
'BOARD_VERSION' => $config['version'],
|
||||
|
||||
'U_ACTION' => $this->u_action,
|
||||
'U_ADMIN_LOG' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=logs&mode=admin'),
|
||||
'U_INACTIVE_USERS' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=inactive&mode=list'),
|
||||
'U_VERSIONCHECK' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=update&mode=version_check'),
|
||||
'U_VERSIONCHECK_FORCE' => append_sid("{$phpbb_admin_path}index.$phpEx", 'versioncheck_force=1'),
|
||||
'U_ATTACH_ORPHAN' => append_sid("{$phpbb_admin_path}index.$phpEx", 'i=acp_attachments&mode=orphan'),
|
||||
|
||||
'S_VERSIONCHECK' => ($auth->acl_get('a_board')) ? true : false,
|
||||
'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 = false;
|
||||
|
||||
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'))
|
||||
{
|
||||
$user->add_lang('memberlist');
|
||||
|
||||
$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']),
|
||||
'REMINDED_DATE' => $user->format_date($row['user_reminded_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'],
|
||||
'POSTS' => ($row['user_posts']) ? $row['user_posts'] : 0,
|
||||
'REMINDED' => $row['user_reminded'],
|
||||
|
||||
'REMINDED_EXPLAIN' => $user->lang('USER_LAST_REMINDED', (int) $row['user_reminded'], $user->format_date($row['user_reminded_time'])),
|
||||
|
||||
'USERNAME_FULL' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, append_sid("{$phpbb_admin_path}index.$phpEx", 'i=users&mode=overview')),
|
||||
'USERNAME' => get_username_string('username', $row['user_id'], $row['username'], $row['user_colour']),
|
||||
'USER_COLOR' => get_username_string('colour', $row['user_id'], $row['username'], $row['user_colour']),
|
||||
|
||||
'U_USER_ADMIN' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=users&mode=overview&u={$row['user_id']}"),
|
||||
'U_SEARCH_USER' => ($auth->acl_get('u_search')) ? append_sid("{$phpbb_root_path}search.$phpEx", "author_id={$row['user_id']}&sr=posts") : '',
|
||||
));
|
||||
}
|
||||
|
||||
$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') && !is_file($phpbb_root_path . 'install'))
|
||||
{
|
||||
$template->assign_var('S_REMOVE_INSTALL', true);
|
||||
}
|
||||
|
||||
// Warn if no search index is created
|
||||
if ($config['num_posts'] && class_exists($config['search_type']))
|
||||
{
|
||||
$error = false;
|
||||
$search_type = $config['search_type'];
|
||||
$search = new $search_type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
|
||||
|
||||
if (!$search->index_created())
|
||||
{
|
||||
$template->assign_vars(array(
|
||||
'S_SEARCH_INDEX_MISSING' => true,
|
||||
'L_NO_SEARCH_INDEX' => $user->lang('NO_SEARCH_INDEX', $search->get_name(), '<a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", 'i=acp_search&mode=index') . '">', '</a>'),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if (!defined('PHPBB_DISABLE_CONFIG_CHECK') && file_exists($phpbb_root_path . 'config.' . $phpEx) && $phpbb_filesystem->is_writable($phpbb_root_path . 'config.' . $phpEx))
|
||||
{
|
||||
// World-Writable? (000x)
|
||||
$template->assign_var('S_WRITABLE_CONFIG', (bool) (@fileperms($phpbb_root_path . 'config.' . $phpEx) & 0x0002));
|
||||
}
|
||||
|
||||
if (extension_loaded('mbstring'))
|
||||
{
|
||||
$template->assign_vars(array(
|
||||
'S_MBSTRING_LOADED' => true,
|
||||
'S_MBSTRING_FUNC_OVERLOAD_FAIL' => (intval(@ini_get('mbstring.func_overload')) & (MB_OVERLOAD_MAIL | MB_OVERLOAD_STRING)),
|
||||
'S_MBSTRING_ENCODING_TRANSLATION_FAIL' => (@ini_get('mbstring.encoding_translation') != 0),
|
||||
'S_MBSTRING_HTTP_INPUT_FAIL' => !in_array(@ini_get('mbstring.http_input'), array('pass', '')),
|
||||
'S_MBSTRING_HTTP_OUTPUT_FAIL' => !in_array(@ini_get('mbstring.http_output'), array('pass', '')),
|
||||
));
|
||||
}
|
||||
|
||||
// Fill dbms version if not yet filled
|
||||
if (empty($config['dbms_version']))
|
||||
{
|
||||
$config->set('dbms_version', $db->sql_server_info(true));
|
||||
}
|
||||
|
||||
$this->tpl_name = 'acp_main';
|
||||
$this->page_title = 'ACP_MAIN';
|
||||
}
|
||||
}
|
||||
666
includes/acp/acp_modules.php
Normal file
666
includes/acp/acp_modules.php
Normal file
@@ -0,0 +1,666 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
use phpbb\module\exception\module_exception;
|
||||
|
||||
/**
|
||||
* - 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
|
||||
*/
|
||||
|
||||
class acp_modules
|
||||
{
|
||||
var $module_class = '';
|
||||
var $parent_id;
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $module, $request, $phpbb_log, $phpbb_container;
|
||||
|
||||
/** @var \phpbb\module\module_manager $module_manager */
|
||||
$module_manager = $phpbb_container->get('module.manager');
|
||||
|
||||
// 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';
|
||||
|
||||
$form_key = 'acp_modules';
|
||||
add_form_key($form_key);
|
||||
|
||||
// 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->variable('parent_id', 0);
|
||||
$module_id = $request->variable('m', 0);
|
||||
$action = $request->variable('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);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$row = $module_manager->get_module_row($module_id, $this->module_class);
|
||||
$module_manager->delete_module($module_id, $this->module_class);
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_REMOVED', false, array($user->lang($row['module_langname'])));
|
||||
}
|
||||
catch (module_exception $e)
|
||||
{
|
||||
$msg = $user->lang($e->getMessage());
|
||||
trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$module_manager->remove_cache_file($this->module_class);
|
||||
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);
|
||||
}
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_modules'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . 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);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname'])));
|
||||
$module_manager->remove_cache_file($this->module_class);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_modules'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . 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);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$move_module_name = $module_manager->move_module_by($row, $this->module_class, $action, 1);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_' . strtoupper($action), false, array($user->lang($row['module_langname']), $move_module_name));
|
||||
$module_manager->remove_cache_file($this->module_class);
|
||||
}
|
||||
catch (module_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'success' => ($move_module_name !== false),
|
||||
));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'quickadd':
|
||||
$quick_install = $request->variable('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 = $module_manager->get_module_infos($this->module_class, $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'],
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
$module_manager->update_module_data($module_data);
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_MODULE_ADD', false, array($user->lang($module_data['module_langname'])));
|
||||
}
|
||||
catch (\phpbb\module\exception\module_exception $e)
|
||||
{
|
||||
$msg = $user->lang($e->getMessage());
|
||||
trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if (!count($errors))
|
||||
{
|
||||
$module_manager->remove_cache_file($this->module_class);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$module_row = $module_manager->get_module_row($module_id, $this->module_class);
|
||||
}
|
||||
catch (\phpbb\module\exception\module_not_found_exception $e)
|
||||
{
|
||||
$msg = $user->lang($e->getMessage());
|
||||
trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
// no break
|
||||
|
||||
case 'add':
|
||||
|
||||
if ($action == 'add')
|
||||
{
|
||||
$module_row = array(
|
||||
'module_basename' => '',
|
||||
'module_enabled' => 0,
|
||||
'module_display' => 1,
|
||||
'parent_id' => 0,
|
||||
'module_langname' => $request->variable('module_langname', '', true),
|
||||
'module_mode' => '',
|
||||
'module_auth' => '',
|
||||
);
|
||||
}
|
||||
|
||||
$module_data = array();
|
||||
|
||||
$module_data['module_basename'] = $request->variable('module_basename', (string) $module_row['module_basename']);
|
||||
$module_data['module_enabled'] = $request->variable('module_enabled', (int) $module_row['module_enabled']);
|
||||
$module_data['module_display'] = $request->variable('module_display', (int) $module_row['module_display']);
|
||||
$module_data['parent_id'] = $request->variable('module_parent_id', (int) $module_row['parent_id']);
|
||||
$module_data['module_class'] = $this->module_class;
|
||||
$module_data['module_langname'] = $request->variable('module_langname', (string) $module_row['module_langname'], true);
|
||||
$module_data['module_mode'] = $request->variable('module_mode', (string) $module_row['module_mode']);
|
||||
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
|
||||
if ($submit)
|
||||
{
|
||||
if (!check_form_key($form_key))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
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->variable('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 = $module_manager->get_module_infos($this->module_class, $module_data['module_basename']);
|
||||
$module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth'];
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$module_manager->update_module_data($module_data);
|
||||
$phpbb_log->add('admin',
|
||||
$user->data['user_id'],
|
||||
$user->ip,
|
||||
($action === 'edit') ? 'LOG_MODULE_EDIT' : 'LOG_MODULE_ADD',
|
||||
false,
|
||||
array($user->lang($module_data['module_langname']))
|
||||
); }
|
||||
catch (\phpbb\module\exception\module_exception $e)
|
||||
{
|
||||
$msg = $user->lang($e->getMessage());
|
||||
trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if (!count($errors))
|
||||
{
|
||||
$module_manager->remove_cache_file($this->module_class);
|
||||
|
||||
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 = $module_manager->get_module_infos($this->module_class);
|
||||
|
||||
// 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"' : '') . '>' . $user->lang($values['title']) . ' [' . $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"' : '') . '>' . $user->lang($m_values['title']) . '</option>';
|
||||
}
|
||||
|
||||
$template->assign_block_vars('m_names.modes', array(
|
||||
'OPTION' => $m_mode,
|
||||
'VALUE' => $user->lang($m_values['title']),
|
||||
'A_OPTION' => addslashes($m_mode),
|
||||
'A_VALUE' => addslashes($user->lang($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' => $user->lang($module_data['module_langname']),
|
||||
'ACTION' => $action,
|
||||
'MODULE_ID' => $module_id,
|
||||
|
||||
),
|
||||
array_change_key_case($module_data, CASE_UPPER))
|
||||
);
|
||||
|
||||
if (count($errors))
|
||||
{
|
||||
$template->assign_vars(array(
|
||||
'S_ERROR' => true,
|
||||
'ERROR_MSG' => implode('<br />', $errors))
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// Default management page
|
||||
if (count($errors))
|
||||
{
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'MESSAGE_TITLE' => $user->lang('ERROR'),
|
||||
'MESSAGE_TEXT' => implode('<br />', $errors),
|
||||
'SUCCESS' => false,
|
||||
));
|
||||
}
|
||||
|
||||
$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 = $module_manager->get_module_branch($this->parent_id, $this->module_class, 'parents');
|
||||
|
||||
foreach ($modules_nav as $row)
|
||||
{
|
||||
$langname = $user->lang($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 = $user->lang($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&hash=' . generate_link_hash('acp_modules'),
|
||||
'U_MOVE_DOWN' => $url . '&action=move_down&hash=' . generate_link_hash('acp_modules'),
|
||||
'U_EDIT' => $url . '&action=edit',
|
||||
'U_DELETE' => $url . '&action=delete',
|
||||
'U_ENABLE' => $url . '&action=enable&hash=' . generate_link_hash('acp_modules'),
|
||||
'U_DISABLE' => $url . '&action=disable&hash=' . generate_link_hash('acp_modules'))
|
||||
);
|
||||
}
|
||||
while ($row = $db->sql_fetchrow($result));
|
||||
}
|
||||
else if ($this->parent_id)
|
||||
{
|
||||
try
|
||||
{
|
||||
$row = $module_manager->get_module_row($this->parent_id, $this->module_class);
|
||||
}
|
||||
catch (\phpbb\module\exception\module_not_found_exception $e)
|
||||
{
|
||||
$msg = $user->lang($e->getMessage());
|
||||
trigger_error($msg . adm_back_link($this->u_action . '&parent_id=' . $this->parent_id), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$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&hash=' . generate_link_hash('acp_modules'),
|
||||
'U_DISABLE' => $url . '&action=disable&hash=' . generate_link_hash('acp_modules'))
|
||||
);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// Quick adding module
|
||||
$module_infos = $module_manager->get_module_infos($this->module_class);
|
||||
|
||||
// Build quick options
|
||||
$s_install_options = '';
|
||||
foreach ($module_infos as $option => $values)
|
||||
{
|
||||
// Name options
|
||||
$s_install_options .= '<optgroup label="' . $user->lang($values['title']) . ' [' . $option . ']">';
|
||||
|
||||
// Build module modes
|
||||
foreach ($values['modes'] as $m_mode => $m_values)
|
||||
{
|
||||
$s_install_options .= '<option value="' . $option . '::' . $m_mode . '"> ' . $user->lang($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,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
$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 (!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 = $user->lang($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;
|
||||
}
|
||||
}
|
||||
596
includes/acp/acp_permission_roles.php
Normal file
596
includes/acp/acp_permission_roles.php
Normal file
@@ -0,0 +1,596 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_permission_roles
|
||||
{
|
||||
var $u_action;
|
||||
protected $auth_admin;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $phpbb_container;
|
||||
global $phpbb_root_path, $phpEx;
|
||||
global $request, $phpbb_log;
|
||||
|
||||
if (!function_exists('user_get_id_name'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
if (!class_exists('auth_admin'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/acp/auth.' . $phpEx);
|
||||
}
|
||||
|
||||
$this->auth_admin = new auth_admin();
|
||||
|
||||
$user->add_lang('acp/permissions');
|
||||
add_permission_language();
|
||||
|
||||
$this->tpl_name = 'acp_permission_roles';
|
||||
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
$role_id = $request->variable('role_id', 0);
|
||||
$action = $request->variable('action', '');
|
||||
$action = (isset($_POST['add'])) ? 'add' : $action;
|
||||
|
||||
$form_name = 'acp_permissions';
|
||||
add_form_key($form_name);
|
||||
|
||||
if (!$role_id && in_array($action, array('remove', 'edit', 'move_up', 'move_down')))
|
||||
{
|
||||
trigger_error($user->lang['NO_ROLE_SELECTED'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
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':
|
||||
|
||||
$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'];
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_REMOVED', false, array($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':
|
||||
|
||||
// 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 = $request->variable('role_name', '', true);
|
||||
$role_description = $request->variable('role_description', '', true);
|
||||
$auth_settings = $request->variable('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
|
||||
$this->auth_admin->acl_set_role($role_id, $auth_settings);
|
||||
|
||||
$role_name = (!empty($user->lang[$role_name])) ? $user->lang[$role_name] : $role_name;
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_' . strtoupper($permission_type) . 'ROLE_' . strtoupper($action), false, array($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->variable('options_from', 0);
|
||||
|
||||
$role_row = array(
|
||||
'role_name' => $request->variable('role_name', '', true),
|
||||
'role_description' => $request->variable('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->get_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')
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
/* @var $phpbb_permissions \phpbb\permissions */
|
||||
$phpbb_permissions = $phpbb_container->get('acl.permissions');
|
||||
|
||||
$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' => $phpbb_permissions->get_type_lang($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->get_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 = $this->auth_admin->get_role_mask($role_id);
|
||||
|
||||
if (count($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))
|
||||
);
|
||||
|
||||
$this->auth_admin->display_role_mask($hold_ary);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
break;
|
||||
|
||||
case 'move_up':
|
||||
case 'move_down':
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_permission_roles'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$sql = 'SELECT role_order
|
||||
FROM ' . ACL_ROLES_TABLE . "
|
||||
WHERE role_id = $role_id";
|
||||
$result = $db->sql_query($sql);
|
||||
$order = $db->sql_fetchfield('role_order');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if ($order === false || ($order == 0 && $action == 'move_up'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
$order = (int) $order;
|
||||
$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);
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'success' => (bool) $db->sql_affectedrows(),
|
||||
));
|
||||
}
|
||||
|
||||
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->variable('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&role_id=' . $row['role_id'] . '&hash=' . generate_link_hash('acp_permission_roles'),
|
||||
'U_MOVE_DOWN' => $this->u_action . '&action=move_down&role_id=' . $row['role_id'] . '&hash=' . generate_link_hash('acp_permission_roles'),
|
||||
'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 = $this->auth_admin->get_role_mask($display_item);
|
||||
$this->auth_admin->display_role_mask($hold_ary);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display permission settings able to be set
|
||||
*/
|
||||
function display_auth_options($auth_options)
|
||||
{
|
||||
global $template, $phpbb_container;
|
||||
|
||||
/* @var $phpbb_permissions \phpbb\permissions */
|
||||
$phpbb_permissions = $phpbb_container->get('acl.permissions');
|
||||
|
||||
$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)
|
||||
$this->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', count($categories));
|
||||
|
||||
// Assign to template
|
||||
foreach ($content_array as $cat => $cat_array)
|
||||
{
|
||||
$template->assign_block_vars('auth', array(
|
||||
'CAT_NAME' => $phpbb_permissions->get_category_lang($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' => $phpbb_permissions->get_permission_lang($permission),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove role
|
||||
*/
|
||||
function remove_role($role_id, $permission_type)
|
||||
{
|
||||
global $db;
|
||||
|
||||
// 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->get_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 = $this->auth_admin->get_role_mask($role_id);
|
||||
|
||||
// Re-assign permissions
|
||||
foreach ($hold_ary as $forum_id => $forum_ary)
|
||||
{
|
||||
if (isset($forum_ary['users']))
|
||||
{
|
||||
$this->auth_admin->acl_set('user', $forum_id, $forum_ary['users'], $auth_settings, 0, false);
|
||||
}
|
||||
|
||||
if (isset($forum_ary['groups']))
|
||||
{
|
||||
$this->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);
|
||||
|
||||
$this->auth_admin->acl_clear_prefetch();
|
||||
}
|
||||
}
|
||||
1346
includes/acp/acp_permissions.php
Normal file
1346
includes/acp/acp_permissions.php
Normal file
File diff suppressed because it is too large
Load Diff
89
includes/acp/acp_php_info.php
Normal file
89
includes/acp/acp_php_info.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_php_info
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $template;
|
||||
|
||||
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[1][0]))
|
||||
{
|
||||
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);
|
||||
|
||||
// Fix invalid anchor names (eg "module_Zend Optimizer")
|
||||
$output = preg_replace_callback('#<a name="([^"]+)">#', array($this, 'remove_spaces'), $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);
|
||||
}
|
||||
|
||||
function remove_spaces($matches)
|
||||
{
|
||||
return '<a name="' . str_replace(' ', '_', $matches[1]) . '">';
|
||||
}
|
||||
}
|
||||
1292
includes/acp/acp_profile.php
Normal file
1292
includes/acp/acp_profile.php
Normal file
File diff suppressed because it is too large
Load Diff
587
includes/acp/acp_prune.php
Normal file
587
includes/acp/acp_prune.php
Normal file
@@ -0,0 +1,587 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_prune
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $user, $phpEx, $phpbb_root_path;
|
||||
|
||||
$user->add_lang('acp/prune');
|
||||
|
||||
if (!function_exists('user_active_flip'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
|
||||
}
|
||||
|
||||
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, $phpbb_log, $request, $phpbb_dispatcher;
|
||||
|
||||
$all_forums = $request->variable('all_forums', 0);
|
||||
$forum_id = $request->variable('f', array(0));
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
|
||||
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->variable('prune_days', 0);
|
||||
$prune_viewed = $request->variable('prune_vieweddays', 0);
|
||||
$prune_all = (!$prune_posted && !$prune_viewed) ? true : false;
|
||||
|
||||
$prune_flags = 0;
|
||||
$prune_flags += ($request->variable('prune_old_polls', 0)) ? 2 : 0;
|
||||
$prune_flags += ($request->variable('prune_announce', 0)) ? 4 : 0;
|
||||
$prune_flags += ($request->variable('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 = (count($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);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PRUNE', false, array($log_data));
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
$hidden_fields = array(
|
||||
'i' => $id,
|
||||
'mode' => $mode,
|
||||
'submit' => 1,
|
||||
'all_forums' => $all_forums,
|
||||
'f' => $forum_id,
|
||||
|
||||
'prune_days' => $request->variable('prune_days', 0),
|
||||
'prune_vieweddays' => $request->variable('prune_vieweddays', 0),
|
||||
'prune_old_polls' => $request->variable('prune_old_polls', 0),
|
||||
'prune_announce' => $request->variable('prune_announce', 0),
|
||||
'prune_sticky' => $request->variable('prune_sticky', 0),
|
||||
);
|
||||
|
||||
/**
|
||||
* Use this event to pass data from the prune form to the confirmation screen
|
||||
*
|
||||
* @event core.prune_forums_settings_confirm
|
||||
* @var array hidden_fields Hidden fields that are passed through the confirm screen
|
||||
* @since 3.2.2-RC1
|
||||
*/
|
||||
$vars = array('hidden_fields');
|
||||
extract($phpbb_dispatcher->trigger_event('core.prune_forums_settings_confirm', compact($vars)));
|
||||
|
||||
confirm_box(false, $user->lang['PRUNE_FORUM_CONFIRM'], build_hidden_fields($hidden_fields));
|
||||
}
|
||||
}
|
||||
|
||||
// If they haven't selected a forum for pruning yet then
|
||||
// display a select box to use for pruning.
|
||||
if (!count($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 = (count($forum_id) == 1) ? 'SELECTED_FORUM' : 'SELECTED_FORUMS';
|
||||
|
||||
$template_data = 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,
|
||||
);
|
||||
|
||||
/**
|
||||
* Event to add/modify prune forums settings template data
|
||||
*
|
||||
* @event core.prune_forums_settings_template_data
|
||||
* @var array template_data Array with form template data
|
||||
* @since 3.2.2-RC1
|
||||
*/
|
||||
$vars = array('template_data');
|
||||
extract($phpbb_dispatcher->trigger_event('core.prune_forums_settings_template_data', compact($vars)));
|
||||
|
||||
$template->assign_vars($template_data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prune users
|
||||
*/
|
||||
function prune_users($id, $mode)
|
||||
{
|
||||
global $db, $user, $auth, $template, $phpbb_log, $request;
|
||||
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $phpbb_container;
|
||||
|
||||
/** @var \phpbb\group\helper $group_helper */
|
||||
$group_helper = $phpbb_container->get('group_helper');
|
||||
|
||||
$user->add_lang('memberlist');
|
||||
|
||||
$prune = (isset($_POST['prune'])) ? true : false;
|
||||
|
||||
if ($prune)
|
||||
{
|
||||
$action = $request->variable('action', 'deactivate');
|
||||
$deleteposts = $request->variable('deleteposts', 0);
|
||||
|
||||
if (confirm_box(true))
|
||||
{
|
||||
$user_ids = $usernames = array();
|
||||
|
||||
$this->get_prune_users($user_ids, $usernames);
|
||||
if (count($user_ids))
|
||||
{
|
||||
if ($action == 'deactivate')
|
||||
{
|
||||
user_active_flip('deactivate', $user_ids);
|
||||
$l_log = 'LOG_PRUNE_USER_DEAC';
|
||||
}
|
||||
else if ($action == 'delete')
|
||||
{
|
||||
if ($deleteposts)
|
||||
{
|
||||
user_delete('remove', $user_ids);
|
||||
|
||||
$l_log = 'LOG_PRUNE_USER_DEL_DEL';
|
||||
}
|
||||
else
|
||||
{
|
||||
user_delete('retain', $user_ids, true);
|
||||
|
||||
$l_log = 'LOG_PRUNE_USER_DEL_ANON';
|
||||
}
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, $l_log, false, array(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 (!count($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],
|
||||
'USER_ID' => $user_id,
|
||||
'U_PROFILE' => get_username_string('profile', $user_id, $usernames[$user_id]),
|
||||
'U_USER_ADMIN' => ($auth->acl_get('a_user')) ? append_sid("{$phpbb_admin_path}index.$phpEx", '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,
|
||||
|
||||
'deleteposts' => $request->variable('deleteposts', 0),
|
||||
'action' => $request->variable('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_active_time = '';
|
||||
foreach ($find_time as $key => $value)
|
||||
{
|
||||
$s_find_active_time .= '<option value="' . $key . '">' . $value . '</option>';
|
||||
}
|
||||
|
||||
$sql = 'SELECT group_id, group_name
|
||||
FROM ' . GROUPS_TABLE . '
|
||||
WHERE group_type <> ' . GROUP_SPECIAL . '
|
||||
ORDER BY group_name ASC';
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$s_group_list = '';
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$s_group_list .= '<option value="' . $row['group_id'] . '">' . $group_helper->get_name($row['group_name']) . '</option>';
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if ($s_group_list)
|
||||
{
|
||||
// Only prepend the "All groups" option if there are groups,
|
||||
// otherwise we don't want to display this option at all.
|
||||
$s_group_list = '<option value="0">' . $user->lang['PRUNE_USERS_GROUP_NONE'] . '</option>' . $s_group_list;
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'U_ACTION' => $this->u_action,
|
||||
'S_ACTIVE_OPTIONS' => $s_find_active_time,
|
||||
'S_GROUP_LIST' => $s_group_list,
|
||||
'S_COUNT_OPTIONS' => $s_find_count,
|
||||
'U_FIND_USERNAME' => append_sid("{$phpbb_root_path}memberlist.$phpEx", '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, $request;
|
||||
|
||||
$users_by_name = $request->variable('users', '', true);
|
||||
$users_by_id = $request->variable('user_ids', array(0));
|
||||
$group_id = $request->variable('group_id', 0);
|
||||
$posts_on_queue = (trim($request->variable('posts_on_queue', '')) === '') ? false : $request->variable('posts_on_queue', 0);
|
||||
|
||||
if ($users_by_name)
|
||||
{
|
||||
$users = explode("\n", $users_by_name);
|
||||
$where_sql = ' AND ' . $db->sql_in_set('username_clean', array_map('utf8_clean_string', $users));
|
||||
}
|
||||
else if (!empty($users_by_id))
|
||||
{
|
||||
$user_ids = $users_by_id;
|
||||
user_get_id_name($user_ids, $usernames);
|
||||
|
||||
$where_sql = ' AND ' . $db->sql_in_set('user_id', $user_ids);
|
||||
}
|
||||
else
|
||||
{
|
||||
$username = $request->variable('username', '', true);
|
||||
$email = $request->variable('email', '');
|
||||
|
||||
$active_select = $request->variable('active_select', 'lt');
|
||||
$count_select = $request->variable('count_select', 'eq');
|
||||
$queue_select = $request->variable('queue_select', 'gt');
|
||||
$joined_before = $request->variable('joined_before', '');
|
||||
$joined_after = $request->variable('joined_after', '');
|
||||
$active = $request->variable('active', '');
|
||||
|
||||
$count = ($request->variable('count', '') === '') ? false : $request->variable('count', 0);
|
||||
|
||||
$active = ($active) ? explode('-', $active) : array();
|
||||
$joined_before = ($joined_before) ? explode('-', $joined_before) : array();
|
||||
$joined_after = ($joined_after) ? explode('-', $joined_after) : array();
|
||||
|
||||
// calculate the conditions required by the join time criteria
|
||||
$joined_sql = '';
|
||||
if (!empty($joined_before) && !empty($joined_after))
|
||||
{
|
||||
// if the two entered dates are equal, we need to adjust
|
||||
// so that our time range is a full day instead of 1 second
|
||||
if ($joined_after == $joined_before)
|
||||
{
|
||||
$joined_after[2] += 1;
|
||||
}
|
||||
|
||||
$joined_sql = ' AND user_regdate BETWEEN ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]) .
|
||||
' AND ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[0]);
|
||||
}
|
||||
else if (empty($joined_before) && !empty($joined_after))
|
||||
{
|
||||
$joined_sql = ' AND user_regdate > ' . gmmktime(0, 0, 0, (int) $joined_after[1], (int) $joined_after[2], (int) $joined_after[0]);
|
||||
}
|
||||
else if (empty($joined_after) && !empty($joined_before))
|
||||
{
|
||||
$joined_sql = ' AND user_regdate < ' . gmmktime(0, 0, 0, (int) $joined_before[1], (int) $joined_before[2], (int) $joined_before[0]);
|
||||
}
|
||||
// implicit else when both arrays are empty do nothing
|
||||
|
||||
if ((count($active) && count($active) != 3) || (count($joined_before) && count($joined_before) != 3) || (count($joined_after) && count($joined_after) != 3))
|
||||
{
|
||||
trigger_error($user->lang['WRONG_ACTIVE_JOINED_DATE'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$key_match = array('lt' => '<', 'gt' => '>', 'eq' => '=');
|
||||
|
||||
$where_sql = '';
|
||||
$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), utf8_clean_string($username))) : '';
|
||||
$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->get_any_char(), $email)) . ' ' : '';
|
||||
$where_sql .= $joined_sql;
|
||||
$where_sql .= ($count !== false) ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';
|
||||
|
||||
// First handle pruning of users who never logged in, last active date is 0000-00-00
|
||||
if (count($active) && (int) $active[0] == 0 && (int) $active[1] == 0 && (int) $active[2] == 0)
|
||||
{
|
||||
$where_sql .= ' AND user_lastvisit = 0';
|
||||
}
|
||||
else if (count($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 (count($active))
|
||||
{
|
||||
$where_sql .= ' AND (user_lastvisit > 0 AND user_lastvisit < ' . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]) . ')';
|
||||
}
|
||||
}
|
||||
|
||||
// If no search criteria were provided, go no further.
|
||||
if (!$where_sql && !$group_id && $posts_on_queue === false)
|
||||
{
|
||||
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);
|
||||
|
||||
// Protect the admin, do not prune if no options are given...
|
||||
if ($where_sql)
|
||||
{
|
||||
// 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);
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($group_id)
|
||||
{
|
||||
$sql = 'SELECT u.user_id, u.username
|
||||
FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u
|
||||
WHERE ug.group_id = ' . (int) $group_id . '
|
||||
AND ug.user_id <> ' . ANONYMOUS . '
|
||||
AND u.user_type <> ' . USER_FOUNDER . '
|
||||
AND ug.user_pending = 0
|
||||
AND u.user_id = ug.user_id
|
||||
' . (!empty($user_ids) ? ' AND ' . $db->sql_in_set('ug.user_id', $user_ids) : '');
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
// we're performing an intersection operation, so all the relevant users
|
||||
// come from this most recent query (which was limited to the results of the
|
||||
// previous query)
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($posts_on_queue !== false)
|
||||
{
|
||||
$sql = 'SELECT u.user_id, u.username, COUNT(p.post_id) AS queue_posts
|
||||
FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u
|
||||
WHERE u.user_id <> ' . ANONYMOUS . '
|
||||
AND u.user_type <> ' . USER_FOUNDER . '
|
||||
AND ' . $db->sql_in_set('p.post_visibility', array(ITEM_UNAPPROVED, ITEM_REAPPROVE)) . '
|
||||
AND u.user_id = p.poster_id
|
||||
' . (!empty($user_ids) ? ' AND ' . $db->sql_in_set('p.poster_id', $user_ids) : '') . '
|
||||
GROUP BY p.poster_id
|
||||
HAVING queue_posts ' . $key_match[$queue_select] . ' ' . $posts_on_queue;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
// same intersection logic as the above group ID portion
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
285
includes/acp/acp_ranks.php
Normal file
285
includes/acp/acp_ranks.php
Normal file
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_ranks
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $cache, $request, $phpbb_dispatcher;
|
||||
global $config, $phpbb_root_path, $phpbb_admin_path, $phpbb_log;
|
||||
|
||||
$user->add_lang('acp/posting');
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$action = (isset($_POST['add'])) ? 'add' : $action;
|
||||
$action = (isset($_POST['save'])) ? 'save' : $action;
|
||||
$rank_id = $request->variable('id', 0);
|
||||
|
||||
$this->tpl_name = 'acp_ranks';
|
||||
$this->page_title = 'ACP_MANAGE_RANKS';
|
||||
|
||||
$form_name = 'acp_ranks';
|
||||
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 = $request->variable('title', '', true);
|
||||
$special_rank = $request->variable('special_rank', 0);
|
||||
$min_posts = ($special_rank) ? 0 : max(0, $request->variable('min_posts', 0));
|
||||
$rank_image = $request->variable('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)
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify the SQL array when saving a rank
|
||||
*
|
||||
* @event core.acp_ranks_save_modify_sql_ary
|
||||
* @var int rank_id The ID of the rank (if available)
|
||||
* @var array sql_ary Array with the rank's data
|
||||
* @since 3.1.0-RC3
|
||||
*/
|
||||
$vars = array('rank_id', 'sql_ary');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_ranks_save_modify_sql_ary', compact($vars)));
|
||||
|
||||
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'];
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_UPDATED', false, array($rank_title));
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = 'INSERT INTO ' . RANKS_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
|
||||
$message = $user->lang['RANK_ADDED'];
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_ADDED', false, array($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');
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_RANK_REMOVED', false, array($rank_title));
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'MESSAGE_TITLE' => $user->lang['INFORMATION'],
|
||||
'MESSAGE_TEXT' => $user->lang['RANK_REMOVED'],
|
||||
'REFRESH_DATA' => array(
|
||||
'time' => 3
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
||||
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':
|
||||
|
||||
$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 ($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 . ((in_array($img, $existing_imgs)) ? ' ' . $user->lang['RANK_IMAGE_IN_USE'] : '') . '</option>';
|
||||
}
|
||||
}
|
||||
|
||||
$filename_list = '<option value=""' . (($edit_img == '') ? ' selected="selected"' : '') . '>----------</option>' . $filename_list;
|
||||
unset($existing_imgs, $imglist);
|
||||
|
||||
$tpl_ary = 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 : htmlspecialchars($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,
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify the template output array for editing/adding ranks
|
||||
*
|
||||
* @event core.acp_ranks_edit_modify_tpl_ary
|
||||
* @var array ranks Array with the rank's data
|
||||
* @var array tpl_ary Array with the rank's template data
|
||||
* @since 3.1.0-RC3
|
||||
*/
|
||||
$vars = array('ranks', 'tpl_ary');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_ranks_edit_modify_tpl_ary', compact($vars)));
|
||||
|
||||
$template->assign_vars($tpl_ary);
|
||||
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))
|
||||
{
|
||||
$rank_row = 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'],
|
||||
);
|
||||
|
||||
/**
|
||||
* Modify the template output array for each listed rank
|
||||
*
|
||||
* @event core.acp_ranks_list_modify_rank_row
|
||||
* @var array row Array with the rank's data
|
||||
* @var array rank_row Array with the rank's template data
|
||||
* @since 3.1.0-RC3
|
||||
*/
|
||||
$vars = array('row', 'rank_row');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_ranks_list_modify_rank_row', compact($vars)));
|
||||
|
||||
$template->assign_block_vars('ranks', $rank_row);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
}
|
||||
}
|
||||
394
includes/acp/acp_reasons.php
Normal file
394
includes/acp/acp_reasons.php
Normal file
@@ -0,0 +1,394 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_reasons
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template;
|
||||
global $request, $phpbb_log;
|
||||
|
||||
$user->add_lang(array('mcp', 'acp/posting'));
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
$reason_id = $request->variable('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' => $request->variable('reason_title', '', true),
|
||||
'reason_description' => $request->variable('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 (!count($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';
|
||||
}
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_' . $log, false, array($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' => (count($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($user->lang['COMMA_SEPARATOR'], array_map('htmlspecialchars', array_keys($user->lang['report_reasons']['TITLE']))),
|
||||
'S_EDIT_REASON' => true,
|
||||
'S_TRANSLATED' => $translated,
|
||||
'S_ERROR' => (count($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
|
||||
FROM ' . REPORTS_REASONS_TABLE . "
|
||||
WHERE LOWER(reason_title) = 'other'";
|
||||
$result = $db->sql_query($sql);
|
||||
$other_reason_id = (int) $db->sql_fetchfield('reason_id');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
switch ($db->get_sql_layer())
|
||||
{
|
||||
// The ugly one!
|
||||
case 'mysqli':
|
||||
case 'mysql4':
|
||||
case 'mysql':
|
||||
// Change the reports using this reason to 'other'
|
||||
$sql = 'UPDATE ' . REPORTS_TABLE . '
|
||||
SET reason_id = ' . $other_reason_id . ", report_text = CONCAT('" . $db->sql_escape($reason_row['reason_description']) . "\n\n', report_text)
|
||||
WHERE reason_id = $reason_id";
|
||||
break;
|
||||
|
||||
// Standard? What's that?
|
||||
case 'mssql_odbc':
|
||||
case 'mssqlnative':
|
||||
// Change the reports using this reason to 'other'
|
||||
$sql = "DECLARE @ptrval binary(16)
|
||||
|
||||
SELECT @ptrval = TEXTPTR(report_text)
|
||||
FROM " . REPORTS_TABLE . "
|
||||
WHERE reason_id = " . $reason_id . "
|
||||
|
||||
UPDATETEXT " . REPORTS_TABLE . ".report_text @ptrval 0 0 '" . $db->sql_escape($reason_row['reason_description']) . "\n\n'
|
||||
|
||||
UPDATE " . REPORTS_TABLE . '
|
||||
SET reason_id = ' . $other_reason_id . "
|
||||
WHERE reason_id = $reason_id";
|
||||
break;
|
||||
|
||||
// Teh standard
|
||||
case 'postgres':
|
||||
case 'oracle':
|
||||
case 'sqlite3':
|
||||
// Change the reports using this reason to 'other'
|
||||
$sql = 'UPDATE ' . REPORTS_TABLE . '
|
||||
SET reason_id = ' . $other_reason_id . ", report_text = '" . $db->sql_escape($reason_row['reason_description']) . "\n\n' || report_text
|
||||
WHERE reason_id = $reason_id";
|
||||
break;
|
||||
}
|
||||
$db->sql_query($sql);
|
||||
|
||||
$db->sql_query('DELETE FROM ' . REPORTS_REASONS_TABLE . ' WHERE reason_id = ' . $reason_id);
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_REASON_REMOVED', false, array($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':
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_reasons'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$sql = 'SELECT reason_order
|
||||
FROM ' . REPORTS_REASONS_TABLE . "
|
||||
WHERE reason_id = $reason_id";
|
||||
$result = $db->sql_query($sql);
|
||||
$order = $db->sql_fetchfield('reason_order');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if ($order === false || ($order == 0 && $action == 'move_up'))
|
||||
{
|
||||
break;
|
||||
}
|
||||
$order = (int) $order;
|
||||
$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);
|
||||
|
||||
if ($request->is_ajax())
|
||||
{
|
||||
$json_response = new \phpbb\json_response;
|
||||
$json_response->send(array(
|
||||
'success' => (bool) $db->sql_affectedrows(),
|
||||
));
|
||||
}
|
||||
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&id=' . $row['reason_id'] . '&hash=' . generate_link_hash('acp_reasons'),
|
||||
'U_MOVE_DOWN' => $this->u_action . '&action=move_down&id=' . $row['reason_id'] . '&hash=' . generate_link_hash('acp_reasons'))
|
||||
);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
}
|
||||
623
includes/acp/acp_search.php
Normal file
623
includes/acp/acp_search.php
Normal file
@@ -0,0 +1,623 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
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 $user, $template, $phpbb_log, $request;
|
||||
global $config, $phpbb_admin_path, $phpEx;
|
||||
|
||||
$submit = (isset($_POST['submit'])) ? true : false;
|
||||
|
||||
if ($submit && !check_link_hash($request->variable('hash', ''), 'acp_search'))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
$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',
|
||||
'max_num_search_keywords' => '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 = $search->get_name();
|
||||
|
||||
$selected = ($config['search_type'] == $type) ? ' selected="selected"' : '';
|
||||
$identifier = substr($type, strrpos($type, '\\') + 1);
|
||||
$search_options .= "<option value=\"$type\"$selected data-toggle-setting=\"#search_{$identifier}_settings\">$name</option>";
|
||||
|
||||
if (method_exists($search, 'acp'))
|
||||
{
|
||||
$vars = $search->acp();
|
||||
|
||||
if (!$submit)
|
||||
{
|
||||
$template->assign_block_vars('backend', array(
|
||||
'NAME' => $name,
|
||||
'SETTINGS' => $vars['tpl'],
|
||||
'IDENTIFIER' => $identifier,
|
||||
));
|
||||
}
|
||||
else if (is_array($vars['config']))
|
||||
{
|
||||
$settings = array_merge($settings, $vars['config']);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($search);
|
||||
unset($error);
|
||||
|
||||
$cfg_array = (isset($_REQUEST['config'])) ? $request->variable('config', array('' => ''), true) : array();
|
||||
$updated = $request->variable('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))
|
||||
{
|
||||
$config->set($config_name, $config_value);
|
||||
$updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($submit)
|
||||
{
|
||||
$extra_message = '';
|
||||
if ($updated)
|
||||
{
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, '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()))
|
||||
{
|
||||
$config->set('search_type', $cfg_array['search_type']);
|
||||
|
||||
if (!$updated)
|
||||
{
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_CONFIG_SEARCH');
|
||||
}
|
||||
$extra_message = '<br />' . $user->lang['SWITCHED_SEARCH_BACKEND'] . '<br /><a href="' . append_sid("{$phpbb_admin_path}index.$phpEx", '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'],
|
||||
'MAX_NUM_SEARCH_KEYWORDS' => (int) $config['max_num_search_keywords'],
|
||||
|
||||
'S_SEARCH_TYPES' => $search_options,
|
||||
'S_YES_SEARCH' => (bool) $config['load_search'],
|
||||
'S_SETTINGS' => true,
|
||||
|
||||
'U_ACTION' => $this->u_action . '&hash=' . generate_link_hash('acp_search'))
|
||||
);
|
||||
}
|
||||
|
||||
function index($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $phpbb_log, $request;
|
||||
global $config, $phpbb_admin_path, $phpEx;
|
||||
|
||||
$action = $request->variable('action', '');
|
||||
$this->state = explode(',', $config['search_indexing_state']);
|
||||
|
||||
if (isset($_POST['cancel']))
|
||||
{
|
||||
$action = '';
|
||||
$this->state = array();
|
||||
$this->save_state();
|
||||
}
|
||||
$submit = $request->is_set_post('submit', false);
|
||||
|
||||
if (!check_link_hash($request->variable('hash', ''), 'acp_search') && in_array($action, array('create', 'delete')))
|
||||
{
|
||||
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
if ($action)
|
||||
{
|
||||
switch ($action)
|
||||
{
|
||||
case 'progress_bar':
|
||||
$type = $request->variable('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->variable('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 = $this->search->get_name();
|
||||
|
||||
$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.$phpEx", "i=$id&mode=$mode&action=delete&hash=" . generate_link_hash('acp_search'), 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 = microtime(true);
|
||||
$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 += count($ids);
|
||||
|
||||
if (count($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)
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
meta_refresh(1, append_sid($this->u_action . '&action=delete&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search')));
|
||||
trigger_error($user->lang('SEARCH_INDEX_DELETE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_DELETE_REDIRECT_RATE', $rows_per_second));
|
||||
}
|
||||
}
|
||||
|
||||
$this->search->tidy();
|
||||
|
||||
$this->state = array('');
|
||||
$this->save_state();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_REMOVED', false, array($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.$phpEx", "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 = microtime(true);
|
||||
$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);
|
||||
|
||||
$buffer = $db->sql_buffer_nested_transactions();
|
||||
|
||||
if ($buffer)
|
||||
{
|
||||
$rows = $db->sql_fetchrowset($result);
|
||||
$rows[] = false; // indicate end of array for while loop below
|
||||
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
while ($row = ($buffer ? $rows[$i++] : $db->sql_fetchrow($result)))
|
||||
{
|
||||
// Indexing enabled for this forum
|
||||
if (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++;
|
||||
}
|
||||
if (!$buffer)
|
||||
{
|
||||
$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)
|
||||
{
|
||||
$totaltime = microtime(true) - $starttime;
|
||||
$rows_per_second = $row_count / $totaltime;
|
||||
meta_refresh(1, append_sid($this->u_action . '&action=create&skip_rows=' . $post_counter . '&hash=' . generate_link_hash('acp_search')));
|
||||
trigger_error($user->lang('SEARCH_INDEX_CREATE_REDIRECT', (int) $row_count, $post_counter) . $user->lang('SEARCH_INDEX_CREATE_REDIRECT_RATE', $rows_per_second));
|
||||
}
|
||||
}
|
||||
|
||||
$this->search->tidy();
|
||||
|
||||
$this->state = array('');
|
||||
$this->save_state();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_SEARCH_INDEX_CREATED', false, array($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;
|
||||
foreach ($search_types as $type)
|
||||
{
|
||||
if ($this->init_search($type, $search, $error) || !method_exists($search, 'index_created'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$name = $search->get_name();
|
||||
|
||||
$data = array();
|
||||
if (method_exists($search, 'index_stats'))
|
||||
{
|
||||
$data = $search->index_stats();
|
||||
}
|
||||
|
||||
$statistics = array();
|
||||
foreach ($data as $statistic => $value)
|
||||
{
|
||||
$n = count($statistics);
|
||||
if ($n && count($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) count($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 . '&hash=' . generate_link_hash('acp_search'),
|
||||
'U_PROGRESS_BAR' => append_sid("{$phpbb_admin_path}index.$phpEx", "i=$id&mode=$mode&action=progress_bar"),
|
||||
'UA_PROGRESS_BAR' => addslashes(append_sid("{$phpbb_admin_path}index.$phpEx", "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] . '&hash=' . generate_link_hash('acp_search'),
|
||||
'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()
|
||||
{
|
||||
global $phpbb_extension_manager;
|
||||
|
||||
$finder = $phpbb_extension_manager->get_finder();
|
||||
|
||||
return $finder
|
||||
->extension_suffix('_backend')
|
||||
->extension_directory('/search')
|
||||
->core_path('phpbb/search/')
|
||||
->get_classes();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
global $config;
|
||||
|
||||
if ($state)
|
||||
{
|
||||
$this->state = $state;
|
||||
}
|
||||
|
||||
ksort($this->state);
|
||||
|
||||
$config->set('search_indexing_state', implode(',', $this->state), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises a search backend object
|
||||
*
|
||||
* @return false if no error occurred else an error message
|
||||
*/
|
||||
function init_search($type, &$search, &$error)
|
||||
{
|
||||
global $phpbb_root_path, $phpEx, $user, $auth, $config, $db, $phpbb_dispatcher;
|
||||
|
||||
if (!class_exists($type) || !method_exists($type, 'keyword_search'))
|
||||
{
|
||||
$error = $user->lang['NO_SUCH_SEARCH_MODULE'];
|
||||
return $error;
|
||||
}
|
||||
|
||||
$error = false;
|
||||
$search = new $type($error, $phpbb_root_path, $phpEx, $auth, $config, $db, $user, $phpbb_dispatcher);
|
||||
|
||||
return $error;
|
||||
}
|
||||
}
|
||||
1373
includes/acp/acp_styles.php
Normal file
1373
includes/acp/acp_styles.php
Normal file
File diff suppressed because it is too large
Load Diff
86
includes/acp/acp_update.php
Normal file
86
includes/acp/acp_update.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
class acp_update
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $config, $user, $template, $request;
|
||||
global $phpbb_root_path, $phpEx, $phpbb_container;
|
||||
|
||||
$user->add_lang('install');
|
||||
|
||||
$this->tpl_name = 'acp_update';
|
||||
$this->page_title = 'ACP_VERSION_CHECK';
|
||||
|
||||
/* @var $version_helper \phpbb\version_helper */
|
||||
$version_helper = $phpbb_container->get('version_helper');
|
||||
try
|
||||
{
|
||||
$recheck = $request->variable('versioncheck_force', false);
|
||||
$updates_available = $version_helper->get_update_on_branch($recheck);
|
||||
$upgrades_available = $version_helper->get_suggested_updates();
|
||||
if (!empty($upgrades_available))
|
||||
{
|
||||
$upgrades_available = array_pop($upgrades_available);
|
||||
}
|
||||
}
|
||||
catch (\RuntimeException $e)
|
||||
{
|
||||
$template->assign_var('S_VERSIONCHECK_FAIL', true);
|
||||
|
||||
$updates_available = array();
|
||||
}
|
||||
|
||||
if (!empty($updates_available))
|
||||
{
|
||||
$template->assign_block_vars('updates_available', $updates_available);
|
||||
}
|
||||
|
||||
$update_link = $phpbb_root_path . 'install/app.' . $phpEx;
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_UP_TO_DATE' => empty($updates_available),
|
||||
'U_ACTION' => $this->u_action,
|
||||
'U_VERSIONCHECK_FORCE' => append_sid($this->u_action . '&versioncheck_force=1'),
|
||||
|
||||
'CURRENT_VERSION' => $config['version'],
|
||||
|
||||
'UPDATE_INSTRUCTIONS' => sprintf($user->lang['UPDATE_INSTRUCTIONS'], $update_link),
|
||||
'S_VERSION_UPGRADEABLE' => !empty($upgrades_available),
|
||||
'UPGRADE_INSTRUCTIONS' => !empty($upgrades_available) ? $user->lang('UPGRADE_INSTRUCTIONS', $upgrades_available['current'], $upgrades_available['announcement']) : false,
|
||||
));
|
||||
|
||||
// Incomplete update?
|
||||
if (phpbb_version_compare($config['version'], PHPBB_VERSION, '<'))
|
||||
{
|
||||
$database_update_link = $phpbb_root_path . 'install/app.php/update';
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_UPDATE_INCOMPLETE' => true,
|
||||
'FILES_VERSION' => PHPBB_VERSION,
|
||||
'INCOMPLETE_INSTRUCTIONS' => $user->lang('UPDATE_INCOMPLETE_EXPLAIN', $database_update_link),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
2692
includes/acp/acp_users.php
Normal file
2692
includes/acp/acp_users.php
Normal file
File diff suppressed because it is too large
Load Diff
191
includes/acp/acp_words.php
Normal file
191
includes/acp/acp_words.php
Normal file
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo [words] check regular expressions for special char replacements (stored specialchared in db)
|
||||
*/
|
||||
class acp_words
|
||||
{
|
||||
var $u_action;
|
||||
|
||||
function main($id, $mode)
|
||||
{
|
||||
global $db, $user, $template, $cache, $phpbb_log, $request, $phpbb_container;
|
||||
|
||||
$user->add_lang('acp/posting');
|
||||
|
||||
// Set up general vars
|
||||
$action = $request->variable('action', '');
|
||||
$action = (isset($_POST['add'])) ? 'add' : ((isset($_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->variable('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->variable('id', 0);
|
||||
$word = $request->variable('word', '', true);
|
||||
$replacement = $request->variable('replacement', '', true);
|
||||
|
||||
if ($word === '' || $replacement === '')
|
||||
{
|
||||
trigger_error($user->lang['ENTER_WORD'] . adm_back_link($this->u_action), E_USER_WARNING);
|
||||
}
|
||||
|
||||
// Replace multiple consecutive asterisks with single one as those are not needed
|
||||
$word = preg_replace('#\*{2,}#', '*', $word);
|
||||
|
||||
$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');
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
$log_action = ($word_id) ? 'LOG_WORD_EDIT' : 'LOG_WORD_ADD';
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, $log_action, false, array($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->variable('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');
|
||||
$phpbb_container->get('text_formatter.cache')->invalidate();
|
||||
|
||||
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_WORD_DELETE', false, array($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);
|
||||
}
|
||||
}
|
||||
1323
includes/acp/auth.php
Normal file
1323
includes/acp/auth.php
Normal file
File diff suppressed because it is too large
Load Diff
38
includes/acp/info/acp_attachments.php
Normal file
38
includes/acp/info/acp_attachments.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_attachments_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_attachments',
|
||||
'title' => 'ACP_ATTACHMENTS',
|
||||
'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')),
|
||||
'manage' => array('title' => 'ACP_MANAGE_ATTACHMENTS', 'auth' => 'acl_a_attach', 'cat' => array('ACP_ATTACHMENTS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
36
includes/acp/info/acp_ban.php
Normal file
36
includes/acp/info/acp_ban.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_ban_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_ban',
|
||||
'title' => 'ACP_BAN',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_bbcodes.php
Normal file
34
includes/acp/info/acp_bbcodes.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_bbcodes_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_bbcodes',
|
||||
'title' => 'ACP_BBCODES',
|
||||
'modes' => array(
|
||||
'bbcodes' => array('title' => 'ACP_BBCODES', 'auth' => 'acl_a_bbcode', 'cat' => array('ACP_MESSAGES')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
49
includes/acp/info/acp_board.php
Normal file
49
includes/acp/info/acp_board.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_board_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_board',
|
||||
'title' => 'ACP_BOARD_MANAGEMENT',
|
||||
'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', 'ACP_MESSAGES')),
|
||||
'signature' => array('title' => 'ACP_SIGNATURE_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
|
||||
'feed' => array('title' => 'ACP_FEED_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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_bots.php
Normal file
34
includes/acp/info/acp_bots.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_bots_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_bots',
|
||||
'title' => 'ACP_BOTS',
|
||||
'modes' => array(
|
||||
'bots' => array('title' => 'ACP_BOTS', 'auth' => 'acl_a_bots', 'cat' => array('ACP_GENERAL_TASKS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_captcha.php
Normal file
35
includes/acp/info/acp_captcha.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_captcha_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_captcha',
|
||||
'title' => 'ACP_CAPTCHA',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
30
includes/acp/info/acp_contact.php
Normal file
30
includes/acp/info/acp_contact.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @package module_install
|
||||
*/
|
||||
class acp_contact_info
|
||||
{
|
||||
public function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_contact',
|
||||
'title' => 'ACP_CONTACT',
|
||||
'version' => '1.0.0',
|
||||
'modes' => array(
|
||||
'contact' => array('title' => 'ACP_CONTACT_SETTINGS', 'auth' => 'acl_a_board', 'cat' => array('ACP_BOARD_CONFIGURATION')),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_database.php
Normal file
35
includes/acp/info/acp_database.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_database_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_database',
|
||||
'title' => 'ACP_DATABASE',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_disallow.php
Normal file
34
includes/acp/info/acp_disallow.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_disallow_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_disallow',
|
||||
'title' => 'ACP_DISALLOW',
|
||||
'modes' => array(
|
||||
'usernames' => array('title' => 'ACP_DISALLOW_USERNAMES', 'auth' => 'acl_a_names', 'cat' => array('ACP_USER_SECURITY')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_email.php
Normal file
34
includes/acp/info/acp_email.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_email_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_email',
|
||||
'title' => 'ACP_MASS_EMAIL',
|
||||
'modes' => array(
|
||||
'email' => array('title' => 'ACP_MASS_EMAIL', 'auth' => 'acl_a_email && cfg_email_enable', 'cat' => array('ACP_GENERAL_TASKS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_extensions.php
Normal file
34
includes/acp/info/acp_extensions.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_extensions_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_extensions',
|
||||
'title' => 'ACP_EXTENSION_MANAGEMENT',
|
||||
'modes' => array(
|
||||
'main' => array('title' => 'ACP_EXTENSIONS', 'auth' => 'acl_a_extensions', 'cat' => array('ACP_EXTENSION_MANAGEMENT')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_forums.php
Normal file
34
includes/acp/info/acp_forums.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_forums_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_forums',
|
||||
'title' => 'ACP_FORUM_MANAGEMENT',
|
||||
'modes' => array(
|
||||
'manage' => array('title' => 'ACP_MANAGE_FORUMS', 'auth' => 'acl_a_forum', 'cat' => array('ACP_MANAGE_FORUMS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_groups.php
Normal file
35
includes/acp/info/acp_groups.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_groups_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_groups',
|
||||
'title' => 'ACP_GROUPS_MANAGEMENT',
|
||||
'modes' => array(
|
||||
'manage' => array('title' => 'ACP_GROUPS_MANAGE', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')),
|
||||
'position' => array('title' => 'ACP_GROUPS_POSITION', 'auth' => 'acl_a_group', 'cat' => array('ACP_GROUPS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_help_phpbb.php
Normal file
34
includes/acp/info/acp_help_phpbb.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_help_phpbb_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_help_phpbb',
|
||||
'title' => 'ACP_HELP_PHPBB',
|
||||
'modes' => array(
|
||||
'help_phpbb' => array('title' => 'ACP_HELP_PHPBB', 'auth' => 'acl_a_server', 'cat' => array('ACP_SERVER_CONFIGURATION')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_icons.php
Normal file
35
includes/acp/info/acp_icons.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_icons_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_icons',
|
||||
'title' => 'ACP_ICONS_SMILIES',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_inactive.php
Normal file
34
includes/acp/info/acp_inactive.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_inactive_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_inactive',
|
||||
'title' => 'ACP_INACTIVE_USERS',
|
||||
'modes' => array(
|
||||
'list' => array('title' => 'ACP_INACTIVE_USERS', 'auth' => 'acl_a_user', 'cat' => array('ACP_CAT_USERS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_jabber.php
Normal file
34
includes/acp/info/acp_jabber.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_jabber_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_jabber',
|
||||
'title' => 'ACP_JABBER_SETTINGS',
|
||||
'modes' => array(
|
||||
'settings' => array('title' => 'ACP_JABBER_SETTINGS', 'auth' => 'acl_a_jabber', 'cat' => array('ACP_CLIENT_COMMUNICATION')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_language.php
Normal file
34
includes/acp/info/acp_language.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_language_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_language',
|
||||
'title' => 'ACP_LANGUAGE',
|
||||
'modes' => array(
|
||||
'lang_packs' => array('title' => 'ACP_LANGUAGE_PACKS', 'auth' => 'acl_a_language', 'cat' => array('ACP_LANGUAGE')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
52
includes/acp/info/acp_logs.php
Normal file
52
includes/acp/info/acp_logs.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_logs_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
global $phpbb_dispatcher;
|
||||
|
||||
$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')),
|
||||
);
|
||||
|
||||
/**
|
||||
* Event to add or modify ACP log modulemodes
|
||||
*
|
||||
* @event core.acp_logs_info_modify_modes
|
||||
* @var array modes Array with modes info
|
||||
* @since 3.1.11-RC1
|
||||
* @since 3.2.1-RC1
|
||||
*/
|
||||
$vars = array('modes');
|
||||
extract($phpbb_dispatcher->trigger_event('core.acp_logs_info_modify_modes', compact($vars)));
|
||||
|
||||
return array(
|
||||
'filename' => 'acp_logs',
|
||||
'title' => 'ACP_LOGGING',
|
||||
'modes' => $modes,
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_main.php
Normal file
34
includes/acp/info/acp_main.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_main_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_main',
|
||||
'title' => 'ACP_INDEX',
|
||||
'modes' => array(
|
||||
'main' => array('title' => 'ACP_INDEX', 'auth' => '', 'cat' => array('ACP_CAT_GENERAL')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
36
includes/acp/info/acp_modules.php
Normal file
36
includes/acp/info/acp_modules.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_modules_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_modules',
|
||||
'title' => 'ACP_MODULE_MANAGEMENT',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
37
includes/acp/info/acp_permission_roles.php
Normal file
37
includes/acp/info/acp_permission_roles.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_permission_roles_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_permission_roles',
|
||||
'title' => 'ACP_PERMISSION_ROLES',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
51
includes/acp/info/acp_permissions.php
Normal file
51
includes/acp/info/acp_permissions.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_permissions_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_permissions',
|
||||
'title' => 'ACP_PERMISSIONS',
|
||||
'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_forum_copy' => array('title' => 'ACP_FORUM_PERMISSIONS_COPY', 'auth' => 'acl_a_fauth && acl_a_authusers && acl_a_authgroups && acl_a_mauth', '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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_php_info.php
Normal file
34
includes/acp/info/acp_php_info.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_php_info_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_php_info',
|
||||
'title' => 'ACP_PHP_INFO',
|
||||
'modes' => array(
|
||||
'info' => array('title' => 'ACP_PHP_INFO', 'auth' => 'acl_a_phpinfo', 'cat' => array('ACP_GENERAL_TASKS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_profile.php
Normal file
34
includes/acp/info/acp_profile.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_profile_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_profile',
|
||||
'title' => 'ACP_CUSTOM_PROFILE_FIELDS',
|
||||
'modes' => array(
|
||||
'profile' => array('title' => 'ACP_CUSTOM_PROFILE_FIELDS', 'auth' => 'acl_a_profile', 'cat' => array('ACP_CAT_USERS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_prune.php
Normal file
35
includes/acp/info/acp_prune.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_prune_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_prune',
|
||||
'title' => 'ACP_PRUNING',
|
||||
'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_CAT_USERS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_ranks.php
Normal file
34
includes/acp/info/acp_ranks.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_ranks_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_ranks',
|
||||
'title' => 'ACP_RANKS',
|
||||
'modes' => array(
|
||||
'ranks' => array('title' => 'ACP_MANAGE_RANKS', 'auth' => 'acl_a_ranks', 'cat' => array('ACP_CAT_USERS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_reasons.php
Normal file
34
includes/acp/info/acp_reasons.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_reasons_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_reasons',
|
||||
'title' => 'ACP_REASONS',
|
||||
'modes' => array(
|
||||
'main' => array('title' => 'ACP_MANAGE_REASONS', 'auth' => 'acl_a_reasons', 'cat' => array('ACP_GENERAL_TASKS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_search.php
Normal file
35
includes/acp/info/acp_search.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_search_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_search',
|
||||
'title' => 'ACP_SEARCH',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/acp/info/acp_styles.php
Normal file
35
includes/acp/info/acp_styles.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_styles_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_styles',
|
||||
'title' => 'ACP_CAT_STYLES',
|
||||
'modes' => array(
|
||||
'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
|
||||
'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_update.php
Normal file
34
includes/acp/info/acp_update.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_update_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_update',
|
||||
'title' => 'ACP_UPDATE',
|
||||
'modes' => array(
|
||||
'version_check' => array('title' => 'ACP_VERSION_CHECK', 'auth' => 'acl_a_board', 'cat' => array('ACP_AUTOMATION')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
44
includes/acp/info/acp_users.php
Normal file
44
includes/acp/info/acp_users.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_users_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_users',
|
||||
'title' => 'ACP_USER_MANAGEMENT',
|
||||
'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')),
|
||||
'warnings' => array('title' => 'ACP_USER_WARNINGS', '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()
|
||||
{
|
||||
}
|
||||
}
|
||||
34
includes/acp/info/acp_words.php
Normal file
34
includes/acp/info/acp_words.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class acp_words_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'acp_words',
|
||||
'title' => 'ACP_WORDS',
|
||||
'modes' => array(
|
||||
'words' => array('title' => 'ACP_WORDS', 'auth' => 'acl_a_words', 'cat' => array('ACP_MESSAGES')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
707
includes/bbcode.php
Normal file
707
includes/bbcode.php
Normal file
@@ -0,0 +1,707 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* BBCode class
|
||||
*/
|
||||
class bbcode
|
||||
{
|
||||
var $bbcode_uid = '';
|
||||
var $bbcode_bitfield = '';
|
||||
var $bbcode_cache = array();
|
||||
var $bbcode_template = array();
|
||||
|
||||
var $bbcodes = array();
|
||||
|
||||
var $template_bitfield;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct($bitfield = '')
|
||||
{
|
||||
$this->bbcode_set_bitfield($bitfield);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init bbcode cache entries if bitfield is specified
|
||||
*
|
||||
* @param string $bbcode_bitfield The bbcode bitfield
|
||||
*/
|
||||
function bbcode_set_bitfield($bitfield = '')
|
||||
{
|
||||
if ($bitfield)
|
||||
{
|
||||
$this->bbcode_bitfield = $bitfield;
|
||||
$this->bbcode_cache_init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Second pass bbcodes
|
||||
*/
|
||||
function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false)
|
||||
{
|
||||
if ($bbcode_uid)
|
||||
{
|
||||
$this->bbcode_uid = $bbcode_uid;
|
||||
}
|
||||
|
||||
if ($bbcode_bitfield !== false)
|
||||
{
|
||||
$this->bbcode_bitfield = $bbcode_bitfield;
|
||||
|
||||
// Init those added with a new bbcode_bitfield (already stored codes will not get parsed again)
|
||||
$this->bbcode_cache_init();
|
||||
}
|
||||
|
||||
if (!$this->bbcode_bitfield)
|
||||
{
|
||||
// Remove the uid from tags that have not been transformed into HTML
|
||||
if ($this->bbcode_uid)
|
||||
{
|
||||
$message = str_replace(':' . $this->bbcode_uid, '', $message);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$str = array('search' => array(), 'replace' => array());
|
||||
$preg = array('search' => array(), 'replace' => array());
|
||||
|
||||
$bitfield = new bitfield($this->bbcode_bitfield);
|
||||
$bbcodes_set = $bitfield->get_all_set();
|
||||
|
||||
$undid_bbcode_specialchars = false;
|
||||
foreach ($bbcodes_set as $bbcode_id)
|
||||
{
|
||||
if (!empty($this->bbcode_cache[$bbcode_id]))
|
||||
{
|
||||
foreach ($this->bbcode_cache[$bbcode_id] as $type => $array)
|
||||
{
|
||||
foreach ($array as $search => $replace)
|
||||
{
|
||||
${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search);
|
||||
${$type}['replace'][] = $replace;
|
||||
}
|
||||
|
||||
if (count($str['search']))
|
||||
{
|
||||
$message = str_replace($str['search'], $str['replace'], $message);
|
||||
$str = array('search' => array(), 'replace' => array());
|
||||
}
|
||||
|
||||
if (count($preg['search']))
|
||||
{
|
||||
// we need to turn the entities back into their original form to allow the
|
||||
// search patterns to work properly
|
||||
if (!$undid_bbcode_specialchars)
|
||||
{
|
||||
$message = str_replace(array(':', '.'), array(':', '.'), $message);
|
||||
$undid_bbcode_specialchars = true;
|
||||
}
|
||||
|
||||
foreach ($preg['search'] as $key => $search)
|
||||
{
|
||||
if (is_callable($preg['replace'][$key]))
|
||||
{
|
||||
$message = preg_replace_callback($search, $preg['replace'][$key], $message);
|
||||
}
|
||||
else
|
||||
{
|
||||
$message = preg_replace($search, $preg['replace'][$key], $message);
|
||||
}
|
||||
}
|
||||
|
||||
$preg = array('search' => array(), 'replace' => array());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the uid from tags that have not been transformed into HTML
|
||||
$message = str_replace(':' . $this->bbcode_uid, '', $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init bbcode cache
|
||||
*
|
||||
* requires: $this->bbcode_bitfield
|
||||
* sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield
|
||||
*/
|
||||
function bbcode_cache_init()
|
||||
{
|
||||
global $user, $phpbb_dispatcher, $phpbb_extension_manager, $phpbb_container, $phpbb_filesystem;
|
||||
|
||||
if (empty($this->template_filename))
|
||||
{
|
||||
$this->template_bitfield = new bitfield($user->style['bbcode_bitfield']);
|
||||
|
||||
$template = new \phpbb\template\twig\twig(
|
||||
$phpbb_container->get('path_helper'),
|
||||
$phpbb_container->get('config'),
|
||||
new \phpbb\template\context(),
|
||||
new \phpbb\template\twig\environment(
|
||||
$phpbb_container->get('config'),
|
||||
$phpbb_container->get('filesystem'),
|
||||
$phpbb_container->get('path_helper'),
|
||||
$phpbb_container->getParameter('core.cache_dir'),
|
||||
$phpbb_container->get('ext.manager'),
|
||||
new \phpbb\template\twig\loader(
|
||||
$phpbb_filesystem
|
||||
)
|
||||
),
|
||||
$phpbb_container->getParameter('core.cache_dir'),
|
||||
$phpbb_container->get('user'),
|
||||
$phpbb_container->get('template.twig.extensions.collection'),
|
||||
$phpbb_extension_manager
|
||||
);
|
||||
|
||||
$template->set_style();
|
||||
$template->set_filenames(array('bbcode.html' => 'bbcode.html'));
|
||||
$this->template_filename = $template->get_source_file_for_handle('bbcode.html');
|
||||
}
|
||||
|
||||
$bbcode_ids = $rowset = $sql = array();
|
||||
|
||||
$bitfield = new bitfield($this->bbcode_bitfield);
|
||||
$bbcodes_set = $bitfield->get_all_set();
|
||||
|
||||
foreach ($bbcodes_set as $bbcode_id)
|
||||
{
|
||||
if (isset($this->bbcode_cache[$bbcode_id]))
|
||||
{
|
||||
// do not try to re-cache it if it's already in
|
||||
continue;
|
||||
}
|
||||
$bbcode_ids[] = $bbcode_id;
|
||||
|
||||
if ($bbcode_id > NUM_CORE_BBCODES)
|
||||
{
|
||||
$sql[] = $bbcode_id;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($sql))
|
||||
{
|
||||
global $db;
|
||||
|
||||
$sql = 'SELECT *
|
||||
FROM ' . BBCODES_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('bbcode_id', $sql);
|
||||
$result = $db->sql_query($sql, 3600);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
// To circumvent replacing newlines with <br /> for the generated html,
|
||||
// we use carriage returns here. They are later changed back to newlines
|
||||
$row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']);
|
||||
$row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']);
|
||||
|
||||
$rowset[$row['bbcode_id']] = $row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
// To perform custom second pass in extension, use $this->bbcode_second_pass_by_extension()
|
||||
// method which accepts variable number of parameters
|
||||
foreach ($bbcode_ids as $bbcode_id)
|
||||
{
|
||||
switch ($bbcode_id)
|
||||
{
|
||||
case BBCODE_ID_QUOTE:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array(
|
||||
'[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id)
|
||||
),
|
||||
'preg' => array(
|
||||
'#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#is' => function ($match) {
|
||||
if (!isset($match[2]))
|
||||
{
|
||||
$match[2] = '';
|
||||
}
|
||||
|
||||
return $this->bbcode_second_pass_quote($match[1], $match[2]);
|
||||
},
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_B:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array(
|
||||
'[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id),
|
||||
'[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_I:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array(
|
||||
'[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id),
|
||||
'[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_URL:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
|
||||
'#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_IMG:
|
||||
if ($user->optionget('viewimg'))
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => $this->bbcode_tpl('img', $bbcode_id),
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[img:$uid\](.*?)\[/img:$uid\]#s' => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)),
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case BBCODE_ID_SIZE:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_COLOR:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'!\[color=(#[0-9a-f]{3}|#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_U:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array(
|
||||
'[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id),
|
||||
'[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id),
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_CODE:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#is' => function ($match) {
|
||||
return $this->bbcode_second_pass_code($match[1], $match[2]);
|
||||
},
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_LIST:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1",
|
||||
'#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1",
|
||||
'#\[list=([^\[]+):$uid\]#' => function ($match) {
|
||||
return $this->bbcode_list($match[1]);
|
||||
},
|
||||
),
|
||||
'str' => array(
|
||||
'[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id),
|
||||
'[/list:u:$uid]' => $this->bbcode_tpl('ulist_close', $bbcode_id),
|
||||
'[/list:o:$uid]' => $this->bbcode_tpl('olist_close', $bbcode_id),
|
||||
'[*:$uid]' => $this->bbcode_tpl('listitem', $bbcode_id),
|
||||
'[/*:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id),
|
||||
'[/*:m:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id)
|
||||
),
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_EMAIL:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id),
|
||||
'#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case BBCODE_ID_FLASH:
|
||||
if ($user->optionget('viewflash'))
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => $this->bbcode_tpl('flash', $bbcode_id),
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array(
|
||||
'#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true)))
|
||||
)
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case BBCODE_ID_ATTACH:
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array(
|
||||
'[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id)
|
||||
),
|
||||
'preg' => array(
|
||||
'#\[attachment=([0-9]+):$uid\]#' => $this->bbcode_tpl('inline_attachment_open', $bbcode_id)
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (isset($rowset[$bbcode_id]))
|
||||
{
|
||||
if ($this->template_bitfield->get($bbcode_id))
|
||||
{
|
||||
// The bbcode requires a custom template to be loaded
|
||||
if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id))
|
||||
{
|
||||
// For some reason, the required template seems not to be available, use the default template
|
||||
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// In order to use templates with custom bbcodes we need
|
||||
// to replace all {VARS} to corresponding backreferences
|
||||
// Note that backreferences are numbered from bbcode_match
|
||||
if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|INTTEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m))
|
||||
{
|
||||
foreach ($m[0] as $i => $tok)
|
||||
{
|
||||
$bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Default template
|
||||
$bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl'];
|
||||
}
|
||||
|
||||
// Replace {L_*} lang strings
|
||||
$bbcode_tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
|
||||
return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
|
||||
}, $bbcode_tpl);
|
||||
|
||||
if (!empty($rowset[$bbcode_id]['second_pass_replace']))
|
||||
{
|
||||
// The custom BBCode requires second-pass pattern replacements
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = array(
|
||||
'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->bbcode_cache[$bbcode_id] = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$bbcode_cache = $this->bbcode_cache;
|
||||
$bbcode_bitfield = $this->bbcode_bitfield;
|
||||
$bbcode_uid = $this->bbcode_uid;
|
||||
|
||||
/**
|
||||
* Use this event to modify the bbcode_cache
|
||||
*
|
||||
* @event core.bbcode_cache_init_end
|
||||
* @var array bbcode_cache The array of cached search and replace patterns of bbcodes
|
||||
* @var string bbcode_bitfield The bbcode bitfield
|
||||
* @var string bbcode_uid The bbcode uid
|
||||
* @since 3.1.3-RC1
|
||||
*/
|
||||
$vars = array('bbcode_cache', 'bbcode_bitfield', 'bbcode_uid');
|
||||
extract($phpbb_dispatcher->trigger_event('core.bbcode_cache_init_end', compact($vars)));
|
||||
|
||||
$this->bbcode_cache = $bbcode_cache;
|
||||
$this->bbcode_bitfield = $bbcode_bitfield;
|
||||
$this->bbcode_uid = $bbcode_uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bbcode template
|
||||
*/
|
||||
function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false)
|
||||
{
|
||||
static $bbcode_hardtpl = array();
|
||||
if (empty($bbcode_hardtpl))
|
||||
{
|
||||
global $user;
|
||||
|
||||
$bbcode_hardtpl = array(
|
||||
'b_open' => '<span style="font-weight: bold">',
|
||||
'b_close' => '</span>',
|
||||
'i_open' => '<span style="font-style: italic">',
|
||||
'i_close' => '</span>',
|
||||
'u_open' => '<span style="text-decoration: underline">',
|
||||
'u_close' => '</span>',
|
||||
'img' => '<img src="$1" class="postimage" alt="' . $user->lang['IMAGE'] . '" />',
|
||||
'size' => '<span style="font-size: $1%; line-height: normal">$2</span>',
|
||||
'color' => '<span style="color: $1">$2</span>',
|
||||
'email' => '<a href="mailto:$1">$2</a>'
|
||||
);
|
||||
}
|
||||
|
||||
if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id))
|
||||
{
|
||||
return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false;
|
||||
}
|
||||
|
||||
if (empty($this->bbcode_template))
|
||||
{
|
||||
if (($tpl = file_get_contents($this->template_filename)) === false)
|
||||
{
|
||||
trigger_error('Could not load bbcode template', E_USER_ERROR);
|
||||
}
|
||||
|
||||
// replace \ with \\ and then ' with \'.
|
||||
$tpl = str_replace('\\', '\\\\', $tpl);
|
||||
$tpl = str_replace("'", "\'", $tpl);
|
||||
|
||||
// strip newlines and indent
|
||||
$tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl);
|
||||
|
||||
// Turn template blocks into PHP assignment statements for the values of $bbcode_tpl..
|
||||
$this->bbcode_template = array();
|
||||
|
||||
// Capture the BBCode template matches
|
||||
// Allow phpBB template or the Twig syntax
|
||||
$matches = (preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match)) ?:
|
||||
preg_match_all('#{% for (.*?) in .*? %}(.*?){% endfor %}#s', $tpl, $match);
|
||||
|
||||
for ($i = 0; $i < $matches; $i++)
|
||||
{
|
||||
if (empty($match[1][$i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]);
|
||||
}
|
||||
}
|
||||
|
||||
return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return bbcode template replacement
|
||||
*/
|
||||
function bbcode_tpl_replace($tpl_name, $tpl)
|
||||
{
|
||||
global $user;
|
||||
|
||||
static $replacements = array(
|
||||
'quote_username_open' => array('{USERNAME}' => '$1'),
|
||||
'color' => array('{COLOR}' => '$1', '{TEXT}' => '$2'),
|
||||
'size' => array('{SIZE}' => '$1', '{TEXT}' => '$2'),
|
||||
'img' => array('{URL}' => '$1'),
|
||||
'flash' => array('{WIDTH}' => '$1', '{HEIGHT}' => '$2', '{URL}' => '$3'),
|
||||
'url' => array('{URL}' => '$1', '{DESCRIPTION}' => '$2'),
|
||||
'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2')
|
||||
);
|
||||
|
||||
$tpl = preg_replace_callback('/{L_([A-Z0-9_]+)}/', function ($match) use ($user) {
|
||||
return (!empty($user->lang[$match[1]])) ? $user->lang($match[1]) : ucwords(strtolower(str_replace('_', ' ', $match[1])));
|
||||
}, $tpl);
|
||||
|
||||
if (!empty($replacements[$tpl_name]))
|
||||
{
|
||||
$tpl = strtr($tpl, $replacements[$tpl_name]);
|
||||
}
|
||||
|
||||
return trim($tpl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Second parse list bbcode
|
||||
*/
|
||||
function bbcode_list($type)
|
||||
{
|
||||
if ($type == '')
|
||||
{
|
||||
$tpl = 'ulist_open_default';
|
||||
$type = 'default';
|
||||
}
|
||||
else if ($type == 'i')
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'lower-roman';
|
||||
}
|
||||
else if ($type == 'I')
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'upper-roman';
|
||||
}
|
||||
else if (preg_match('#^(disc|circle|square)$#i', $type))
|
||||
{
|
||||
$tpl = 'ulist_open';
|
||||
$type = strtolower($type);
|
||||
}
|
||||
else if (preg_match('#^[a-z]$#', $type))
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'lower-alpha';
|
||||
}
|
||||
else if (preg_match('#[A-Z]#', $type))
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'upper-alpha';
|
||||
}
|
||||
else if (is_numeric($type))
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'decimal';
|
||||
}
|
||||
else
|
||||
{
|
||||
$tpl = 'olist_open';
|
||||
$type = 'decimal';
|
||||
}
|
||||
|
||||
return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Second parse quote tag
|
||||
*/
|
||||
function bbcode_second_pass_quote($username, $quote)
|
||||
{
|
||||
// when using the /e modifier, preg_replace slashes double-quotes but does not
|
||||
// seem to slash anything else
|
||||
$quote = str_replace('\"', '"', $quote);
|
||||
$username = str_replace('\"', '"', $username);
|
||||
|
||||
// remove newline at the beginning
|
||||
if ($quote == "\n")
|
||||
{
|
||||
$quote = '';
|
||||
}
|
||||
|
||||
$quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote;
|
||||
|
||||
return $quote;
|
||||
}
|
||||
|
||||
/**
|
||||
* Second parse code tag
|
||||
*/
|
||||
function bbcode_second_pass_code($type, $code)
|
||||
{
|
||||
// when using the /e modifier, preg_replace slashes double-quotes but does not
|
||||
// seem to slash anything else
|
||||
$code = str_replace('\"', '"', $code);
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 'php':
|
||||
// Not the english way, but valid because of hardcoded syntax highlighting
|
||||
if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0)
|
||||
{
|
||||
$code = substr($code, 41);
|
||||
}
|
||||
|
||||
// no break;
|
||||
|
||||
default:
|
||||
$code = str_replace("\t", ' ', $code);
|
||||
$code = str_replace(' ', ' ', $code);
|
||||
$code = str_replace(' ', ' ', $code);
|
||||
$code = str_replace("\n ", "\n ", $code);
|
||||
|
||||
// keep space at the beginning
|
||||
if (!empty($code) && $code[0] == ' ')
|
||||
{
|
||||
$code = ' ' . substr($code, 1);
|
||||
}
|
||||
|
||||
// remove newline at the beginning
|
||||
if (!empty($code) && $code[0] == "\n")
|
||||
{
|
||||
$code = substr($code, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
$code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close');
|
||||
|
||||
return $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to perform custom bbcode second pass by extensions
|
||||
* can be used to assign bbcode pattern replacement
|
||||
* Example: '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_second_pass_by_extension('\$1')"
|
||||
*
|
||||
* Accepts variable number of parameters
|
||||
*
|
||||
* @return mixed Second pass result
|
||||
*/
|
||||
function bbcode_second_pass_by_extension()
|
||||
{
|
||||
global $phpbb_dispatcher;
|
||||
|
||||
$return = false;
|
||||
$params_array = func_get_args();
|
||||
|
||||
/**
|
||||
* Event to perform bbcode second pass with
|
||||
* the custom validating methods provided by extensions
|
||||
*
|
||||
* @event core.bbcode_second_pass_by_extension
|
||||
* @var array params_array Array with the function parameters
|
||||
* @var mixed return Second pass result to return
|
||||
*
|
||||
* @since 3.1.5-RC1
|
||||
*/
|
||||
$vars = array('params_array', 'return');
|
||||
extract($phpbb_dispatcher->trigger_event('core.bbcode_second_pass_by_extension', compact($vars)));
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
84
includes/compatibility_globals.php
Normal file
84
includes/compatibility_globals.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets compatibility globals in the global scope
|
||||
*
|
||||
* This function registers compatibility variables to the global
|
||||
* variable scope. This is required to make it possible to include this file
|
||||
* in a service.
|
||||
*/
|
||||
function register_compatibility_globals()
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
global $cache, $phpbb_dispatcher, $request, $user, $auth, $db, $config, $language, $phpbb_log;
|
||||
global $symfony_request, $phpbb_filesystem, $phpbb_path_helper, $phpbb_extension_manager, $template;
|
||||
|
||||
// set up caching
|
||||
/* @var $cache \phpbb\cache\service */
|
||||
$cache = $phpbb_container->get('cache');
|
||||
|
||||
// Instantiate some basic classes
|
||||
/* @var $phpbb_dispatcher \phpbb\event\dispatcher */
|
||||
$phpbb_dispatcher = $phpbb_container->get('dispatcher');
|
||||
|
||||
/* @var $request \phpbb\request\request_interface */
|
||||
$request = $phpbb_container->get('request');
|
||||
// Inject request instance, so only this instance is used with request_var
|
||||
request_var('', 0, false, false, $request);
|
||||
|
||||
/* @var $user \phpbb\user */
|
||||
$user = $phpbb_container->get('user');
|
||||
|
||||
/* @var \phpbb\language\language $language */
|
||||
$language = $phpbb_container->get('language');
|
||||
|
||||
/* @var $auth \phpbb\auth\auth */
|
||||
$auth = $phpbb_container->get('auth');
|
||||
|
||||
/* @var $db \phpbb\db\driver\driver_interface */
|
||||
$db = $phpbb_container->get('dbal.conn');
|
||||
|
||||
// Grab global variables, re-cache if necessary
|
||||
/* @var $config phpbb\config\db */
|
||||
$config = $phpbb_container->get('config');
|
||||
set_config('', '', false, $config);
|
||||
set_config_count('', 0, false, $config);
|
||||
|
||||
/* @var $phpbb_log \phpbb\log\log_interface */
|
||||
$phpbb_log = $phpbb_container->get('log');
|
||||
|
||||
/* @var $symfony_request \phpbb\symfony_request */
|
||||
$symfony_request = $phpbb_container->get('symfony_request');
|
||||
|
||||
/* @var $phpbb_filesystem \phpbb\filesystem\filesystem_interface */
|
||||
$phpbb_filesystem = $phpbb_container->get('filesystem');
|
||||
|
||||
/* @var $phpbb_path_helper \phpbb\path_helper */
|
||||
$phpbb_path_helper = $phpbb_container->get('path_helper');
|
||||
|
||||
// load extensions
|
||||
/* @var $phpbb_extension_manager \phpbb\extension\manager */
|
||||
$phpbb_extension_manager = $phpbb_container->get('ext.manager');
|
||||
|
||||
/* @var $template \phpbb\template\template */
|
||||
$template = $phpbb_container->get('template');
|
||||
}
|
||||
316
includes/constants.php
Normal file
316
includes/constants.php
Normal file
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* valid external constants:
|
||||
* PHPBB_MSG_HANDLER
|
||||
* PHPBB_DB_NEW_LINK
|
||||
* PHPBB_ROOT_PATH
|
||||
* PHPBB_ADMIN_PATH
|
||||
*/
|
||||
|
||||
// phpBB Version
|
||||
@define('PHPBB_VERSION', '3.2.7');
|
||||
|
||||
// QA-related
|
||||
// define('PHPBB_QA', 1);
|
||||
|
||||
// User related
|
||||
define('ANONYMOUS', 1);
|
||||
|
||||
define('USER_ACTIVATION_NONE', 0);
|
||||
define('USER_ACTIVATION_SELF', 1);
|
||||
define('USER_ACTIVATION_ADMIN', 2);
|
||||
define('USER_ACTIVATION_DISABLE', 3);
|
||||
|
||||
define('AVATAR_UPLOAD', 1);
|
||||
define('AVATAR_REMOTE', 2);
|
||||
define('AVATAR_GALLERY', 3);
|
||||
|
||||
define('USER_NORMAL', 0);
|
||||
define('USER_INACTIVE', 1);
|
||||
define('USER_IGNORE', 2);
|
||||
define('USER_FOUNDER', 3);
|
||||
|
||||
define('INACTIVE_REGISTER', 1); // Newly registered account
|
||||
define('INACTIVE_PROFILE', 2); // Profile details changed
|
||||
define('INACTIVE_MANUAL', 3); // Account deactivated by administrator
|
||||
define('INACTIVE_REMIND', 4); // Forced user account reactivation
|
||||
|
||||
// ACL
|
||||
define('ACL_NEVER', 0);
|
||||
define('ACL_YES', 1);
|
||||
define('ACL_NO', -1);
|
||||
|
||||
// Login error codes
|
||||
define('LOGIN_CONTINUE', 1);
|
||||
define('LOGIN_BREAK', 2);
|
||||
define('LOGIN_SUCCESS', 3);
|
||||
define('LOGIN_SUCCESS_CREATE_PROFILE', 20);
|
||||
define('LOGIN_SUCCESS_LINK_PROFILE', 21);
|
||||
define('LOGIN_ERROR_USERNAME', 10);
|
||||
define('LOGIN_ERROR_PASSWORD', 11);
|
||||
define('LOGIN_ERROR_ACTIVE', 12);
|
||||
define('LOGIN_ERROR_ATTEMPTS', 13);
|
||||
define('LOGIN_ERROR_EXTERNAL_AUTH', 14);
|
||||
define('LOGIN_ERROR_PASSWORD_CONVERT', 15);
|
||||
|
||||
// Maximum login attempts
|
||||
// The value is arbitrary, but it has to fit into the user_login_attempts field.
|
||||
define('LOGIN_ATTEMPTS_MAX', 100);
|
||||
|
||||
// Group settings
|
||||
define('GROUP_OPEN', 0);
|
||||
define('GROUP_CLOSED', 1);
|
||||
define('GROUP_HIDDEN', 2);
|
||||
define('GROUP_SPECIAL', 3);
|
||||
define('GROUP_FREE', 4);
|
||||
|
||||
// Forum/Topic states
|
||||
define('FORUM_CAT', 0);
|
||||
define('FORUM_POST', 1);
|
||||
define('FORUM_LINK', 2);
|
||||
define('ITEM_UNLOCKED', 0);
|
||||
define('ITEM_LOCKED', 1);
|
||||
define('ITEM_MOVED', 2);
|
||||
|
||||
define('ITEM_UNAPPROVED', 0); // => has not yet been approved
|
||||
define('ITEM_APPROVED', 1); // => has been approved, and has not been soft deleted
|
||||
define('ITEM_DELETED', 2); // => has been soft deleted
|
||||
define('ITEM_REAPPROVE', 3); // => has been edited and needs to be re-approved
|
||||
|
||||
// Forum Flags
|
||||
define('FORUM_FLAG_LINK_TRACK', 1);
|
||||
define('FORUM_FLAG_PRUNE_POLL', 2);
|
||||
define('FORUM_FLAG_PRUNE_ANNOUNCE', 4);
|
||||
define('FORUM_FLAG_PRUNE_STICKY', 8);
|
||||
define('FORUM_FLAG_ACTIVE_TOPICS', 16);
|
||||
define('FORUM_FLAG_POST_REVIEW', 32);
|
||||
define('FORUM_FLAG_QUICK_REPLY', 64);
|
||||
|
||||
// Forum Options... sequential order. Modifications should begin at number 10 (number 29 is maximum)
|
||||
define('FORUM_OPTION_FEED_NEWS', 1);
|
||||
define('FORUM_OPTION_FEED_EXCLUDE', 2);
|
||||
|
||||
// Optional text flags
|
||||
define('OPTION_FLAG_BBCODE', 1);
|
||||
define('OPTION_FLAG_SMILIES', 2);
|
||||
define('OPTION_FLAG_LINKS', 4);
|
||||
|
||||
// Topic types
|
||||
define('POST_NORMAL', 0);
|
||||
define('POST_STICKY', 1);
|
||||
define('POST_ANNOUNCE', 2);
|
||||
define('POST_GLOBAL', 3);
|
||||
|
||||
// Lastread types
|
||||
define('TRACK_NORMAL', 0);
|
||||
define('TRACK_POSTED', 1);
|
||||
|
||||
// Notify methods
|
||||
define('NOTIFY_EMAIL', 0);
|
||||
define('NOTIFY_IM', 1);
|
||||
define('NOTIFY_BOTH', 2);
|
||||
|
||||
// Notify status
|
||||
define('NOTIFY_YES', 0);
|
||||
define('NOTIFY_NO', 1);
|
||||
|
||||
// Email Priority Settings
|
||||
define('MAIL_LOW_PRIORITY', 4);
|
||||
define('MAIL_NORMAL_PRIORITY', 3);
|
||||
define('MAIL_HIGH_PRIORITY', 2);
|
||||
|
||||
// Log types
|
||||
define('LOG_ADMIN', 0);
|
||||
define('LOG_MOD', 1);
|
||||
define('LOG_CRITICAL', 2);
|
||||
define('LOG_USERS', 3);
|
||||
|
||||
// Private messaging - Do NOT change these values
|
||||
define('PRIVMSGS_HOLD_BOX', -4);
|
||||
define('PRIVMSGS_NO_BOX', -3);
|
||||
define('PRIVMSGS_OUTBOX', -2);
|
||||
define('PRIVMSGS_SENTBOX', -1);
|
||||
define('PRIVMSGS_INBOX', 0);
|
||||
|
||||
// Full Folder Actions
|
||||
define('FULL_FOLDER_NONE', -3);
|
||||
define('FULL_FOLDER_DELETE', -2);
|
||||
define('FULL_FOLDER_HOLD', -1);
|
||||
|
||||
// Download Modes - Attachments
|
||||
define('INLINE_LINK', 1);
|
||||
// This mode is only used internally to allow modders extending the attachment functionality
|
||||
define('PHYSICAL_LINK', 2);
|
||||
|
||||
// Confirm types
|
||||
define('CONFIRM_REG', 1);
|
||||
define('CONFIRM_LOGIN', 2);
|
||||
define('CONFIRM_POST', 3);
|
||||
define('CONFIRM_REPORT', 4);
|
||||
|
||||
// Categories - Attachments
|
||||
define('ATTACHMENT_CATEGORY_NONE', 0);
|
||||
define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images
|
||||
define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming - @deprecated 3.2
|
||||
define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming - @deprecated 3.2
|
||||
define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts
|
||||
define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files
|
||||
define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - @deprecated 3.2
|
||||
|
||||
// BBCode UID length
|
||||
define('BBCODE_UID_LEN', 8);
|
||||
|
||||
// Number of core BBCodes
|
||||
define('NUM_CORE_BBCODES', 12);
|
||||
define('NUM_PREDEFINED_BBCODES', 22);
|
||||
|
||||
// BBCode IDs
|
||||
define('BBCODE_ID_QUOTE', 0);
|
||||
define('BBCODE_ID_B', 1);
|
||||
define('BBCODE_ID_I', 2);
|
||||
define('BBCODE_ID_URL', 3);
|
||||
define('BBCODE_ID_IMG', 4);
|
||||
define('BBCODE_ID_SIZE', 5);
|
||||
define('BBCODE_ID_COLOR', 6);
|
||||
define('BBCODE_ID_U', 7);
|
||||
define('BBCODE_ID_CODE', 8);
|
||||
define('BBCODE_ID_LIST', 9);
|
||||
define('BBCODE_ID_EMAIL', 10);
|
||||
define('BBCODE_ID_FLASH', 11);
|
||||
define('BBCODE_ID_ATTACH', 12);
|
||||
|
||||
// BBCode hard limit
|
||||
define('BBCODE_LIMIT', 1511);
|
||||
|
||||
// Smiley hard limit
|
||||
define('SMILEY_LIMIT', 1000);
|
||||
|
||||
// Magic url types
|
||||
define('MAGIC_URL_EMAIL', 1);
|
||||
define('MAGIC_URL_FULL', 2);
|
||||
define('MAGIC_URL_LOCAL', 3);
|
||||
define('MAGIC_URL_WWW', 4);
|
||||
|
||||
// Profile Field Types
|
||||
define('FIELD_INT', 1);
|
||||
define('FIELD_STRING', 2);
|
||||
define('FIELD_TEXT', 3);
|
||||
define('FIELD_BOOL', 4);
|
||||
define('FIELD_DROPDOWN', 5);
|
||||
define('FIELD_DATE', 6);
|
||||
|
||||
// referer validation
|
||||
define('REFERER_VALIDATE_NONE', 0);
|
||||
define('REFERER_VALIDATE_HOST', 1);
|
||||
define('REFERER_VALIDATE_PATH', 2);
|
||||
|
||||
// phpbb_chmod() permissions
|
||||
@define('CHMOD_ALL', 7);
|
||||
@define('CHMOD_READ', 4);
|
||||
@define('CHMOD_WRITE', 2);
|
||||
@define('CHMOD_EXECUTE', 1);
|
||||
|
||||
// Captcha code length
|
||||
define('CAPTCHA_MIN_CHARS', 4);
|
||||
define('CAPTCHA_MAX_CHARS', 7);
|
||||
|
||||
// Additional constants
|
||||
define('VOTE_CONVERTED', 127);
|
||||
|
||||
// BC global FTW
|
||||
global $table_prefix;
|
||||
|
||||
// Table names
|
||||
define('ACL_GROUPS_TABLE', $table_prefix . 'acl_groups');
|
||||
define('ACL_OPTIONS_TABLE', $table_prefix . 'acl_options');
|
||||
define('ACL_ROLES_DATA_TABLE', $table_prefix . 'acl_roles_data');
|
||||
define('ACL_ROLES_TABLE', $table_prefix . 'acl_roles');
|
||||
define('ACL_USERS_TABLE', $table_prefix . 'acl_users');
|
||||
define('ATTACHMENTS_TABLE', $table_prefix . 'attachments');
|
||||
define('BANLIST_TABLE', $table_prefix . 'banlist');
|
||||
define('BBCODES_TABLE', $table_prefix . 'bbcodes');
|
||||
define('BOOKMARKS_TABLE', $table_prefix . 'bookmarks');
|
||||
define('BOTS_TABLE', $table_prefix . 'bots');
|
||||
@define('CONFIG_TABLE', $table_prefix . 'config');
|
||||
define('CONFIG_TEXT_TABLE', $table_prefix . 'config_text');
|
||||
define('CONFIRM_TABLE', $table_prefix . 'confirm');
|
||||
define('DISALLOW_TABLE', $table_prefix . 'disallow');
|
||||
define('DRAFTS_TABLE', $table_prefix . 'drafts');
|
||||
define('EXT_TABLE', $table_prefix . 'ext');
|
||||
define('EXTENSIONS_TABLE', $table_prefix . 'extensions');
|
||||
define('EXTENSION_GROUPS_TABLE', $table_prefix . 'extension_groups');
|
||||
define('FORUMS_TABLE', $table_prefix . 'forums');
|
||||
define('FORUMS_ACCESS_TABLE', $table_prefix . 'forums_access');
|
||||
define('FORUMS_TRACK_TABLE', $table_prefix . 'forums_track');
|
||||
define('FORUMS_WATCH_TABLE', $table_prefix . 'forums_watch');
|
||||
define('GROUPS_TABLE', $table_prefix . 'groups');
|
||||
define('ICONS_TABLE', $table_prefix . 'icons');
|
||||
define('LANG_TABLE', $table_prefix . 'lang');
|
||||
define('LOG_TABLE', $table_prefix . 'log');
|
||||
define('LOGIN_ATTEMPT_TABLE', $table_prefix . 'login_attempts');
|
||||
define('MIGRATIONS_TABLE', $table_prefix . 'migrations');
|
||||
define('MODERATOR_CACHE_TABLE', $table_prefix . 'moderator_cache');
|
||||
define('MODULES_TABLE', $table_prefix . 'modules');
|
||||
define('NOTIFICATION_TYPES_TABLE', $table_prefix . 'notification_types');
|
||||
define('NOTIFICATIONS_TABLE', $table_prefix . 'notifications');
|
||||
define('POLL_OPTIONS_TABLE', $table_prefix . 'poll_options');
|
||||
define('POLL_VOTES_TABLE', $table_prefix . 'poll_votes');
|
||||
define('POSTS_TABLE', $table_prefix . 'posts');
|
||||
define('PRIVMSGS_TABLE', $table_prefix . 'privmsgs');
|
||||
define('PRIVMSGS_FOLDER_TABLE', $table_prefix . 'privmsgs_folder');
|
||||
define('PRIVMSGS_RULES_TABLE', $table_prefix . 'privmsgs_rules');
|
||||
define('PRIVMSGS_TO_TABLE', $table_prefix . 'privmsgs_to');
|
||||
define('PROFILE_FIELDS_TABLE', $table_prefix . 'profile_fields');
|
||||
define('PROFILE_FIELDS_DATA_TABLE', $table_prefix . 'profile_fields_data');
|
||||
define('PROFILE_FIELDS_LANG_TABLE', $table_prefix . 'profile_fields_lang');
|
||||
define('PROFILE_LANG_TABLE', $table_prefix . 'profile_lang');
|
||||
define('RANKS_TABLE', $table_prefix . 'ranks');
|
||||
define('REPORTS_TABLE', $table_prefix . 'reports');
|
||||
define('REPORTS_REASONS_TABLE', $table_prefix . 'reports_reasons');
|
||||
define('SEARCH_RESULTS_TABLE', $table_prefix . 'search_results');
|
||||
define('SEARCH_WORDLIST_TABLE', $table_prefix . 'search_wordlist');
|
||||
define('SEARCH_WORDMATCH_TABLE', $table_prefix . 'search_wordmatch');
|
||||
define('SESSIONS_TABLE', $table_prefix . 'sessions');
|
||||
define('SESSIONS_KEYS_TABLE', $table_prefix . 'sessions_keys');
|
||||
define('SITELIST_TABLE', $table_prefix . 'sitelist');
|
||||
define('SMILIES_TABLE', $table_prefix . 'smilies');
|
||||
define('SPHINX_TABLE', $table_prefix . 'sphinx');
|
||||
define('STYLES_TABLE', $table_prefix . 'styles');
|
||||
define('STYLES_TEMPLATE_TABLE', $table_prefix . 'styles_template');
|
||||
define('STYLES_TEMPLATE_DATA_TABLE',$table_prefix . 'styles_template_data');
|
||||
define('STYLES_THEME_TABLE', $table_prefix . 'styles_theme');
|
||||
define('STYLES_IMAGESET_TABLE', $table_prefix . 'styles_imageset');
|
||||
define('STYLES_IMAGESET_DATA_TABLE',$table_prefix . 'styles_imageset_data');
|
||||
define('TEAMPAGE_TABLE', $table_prefix . 'teampage');
|
||||
define('TOPICS_TABLE', $table_prefix . 'topics');
|
||||
define('TOPICS_POSTED_TABLE', $table_prefix . 'topics_posted');
|
||||
define('TOPICS_TRACK_TABLE', $table_prefix . 'topics_track');
|
||||
define('TOPICS_WATCH_TABLE', $table_prefix . 'topics_watch');
|
||||
define('USER_GROUP_TABLE', $table_prefix . 'user_group');
|
||||
define('USER_NOTIFICATIONS_TABLE', $table_prefix . 'user_notifications');
|
||||
define('USERS_TABLE', $table_prefix . 'users');
|
||||
define('WARNINGS_TABLE', $table_prefix . 'warnings');
|
||||
define('WORDS_TABLE', $table_prefix . 'words');
|
||||
define('ZEBRA_TABLE', $table_prefix . 'zebra');
|
||||
|
||||
// Additional tables
|
||||
1152
includes/diff/diff.php
Normal file
1152
includes/diff/diff.php
Normal file
File diff suppressed because it is too large
Load Diff
555
includes/diff/engine.php
Normal file
555
includes/diff/engine.php
Normal file
@@ -0,0 +1,555 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Code from pear.php.net, Text_Diff-1.1.0 package
|
||||
* http://pear.php.net/package/Text_Diff/ (native engine)
|
||||
*
|
||||
* Modified by phpBB Limited to meet our coding standards
|
||||
* and being able to integrate into phpBB
|
||||
*
|
||||
* Class used internally by Text_Diff to actually compute the diffs. This
|
||||
* class is implemented using native PHP code.
|
||||
*
|
||||
* The algorithm used here is mostly lifted from the perl module
|
||||
* Algorithm::Diff (version 1.06) by Ned Konz, which is available at:
|
||||
* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip
|
||||
*
|
||||
* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html
|
||||
*
|
||||
* Some ideas (and a bit of code) are taken from analyze.c, of GNU
|
||||
* diffutils-2.7, which can be found at:
|
||||
* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
|
||||
*
|
||||
* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from
|
||||
* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this
|
||||
* code was written by him, and is used/adapted with his permission.
|
||||
*
|
||||
* Copyright 2004-2008 The Horde Project (http://www.horde.org/)
|
||||
*
|
||||
* @author Geoffrey T. Dairiki <dairiki@dairiki.org>
|
||||
* @package diff
|
||||
*
|
||||
* @access private
|
||||
*/
|
||||
class diff_engine
|
||||
{
|
||||
/**
|
||||
* If set to true we trim all lines before we compare them. This ensures that sole space/tab changes do not trigger diffs.
|
||||
*/
|
||||
var $skip_whitespace_changes = true;
|
||||
|
||||
function diff(&$from_lines, &$to_lines, $preserve_cr = true)
|
||||
{
|
||||
// Remove empty lines...
|
||||
// If preserve_cr is true, we basically only change \r\n and bare \r to \n to get the same carriage returns for both files
|
||||
// If it is false, we try to only use \n once per line and ommit all empty lines to be able to get a proper data diff
|
||||
|
||||
if (is_array($from_lines))
|
||||
{
|
||||
$from_lines = implode("\n", $from_lines);
|
||||
}
|
||||
|
||||
if (is_array($to_lines))
|
||||
{
|
||||
$to_lines = implode("\n", $to_lines);
|
||||
}
|
||||
|
||||
if ($preserve_cr)
|
||||
{
|
||||
$from_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $from_lines)));
|
||||
$to_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $to_lines)));
|
||||
}
|
||||
else
|
||||
{
|
||||
$from_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $from_lines));
|
||||
$to_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $to_lines));
|
||||
}
|
||||
|
||||
$n_from = count($from_lines);
|
||||
$n_to = count($to_lines);
|
||||
|
||||
$this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array();
|
||||
unset($this->seq, $this->in_seq, $this->lcs);
|
||||
|
||||
// Skip leading common lines.
|
||||
for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++)
|
||||
{
|
||||
if (trim($from_lines[$skip]) !== trim($to_lines[$skip]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
$this->xchanged[$skip] = $this->ychanged[$skip] = false;
|
||||
}
|
||||
|
||||
// Skip trailing common lines.
|
||||
$xi = $n_from;
|
||||
$yi = $n_to;
|
||||
|
||||
for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++)
|
||||
{
|
||||
if (trim($from_lines[$xi]) !== trim($to_lines[$yi]))
|
||||
{
|
||||
break;
|
||||
}
|
||||
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
|
||||
}
|
||||
|
||||
// Ignore lines which do not exist in both files.
|
||||
for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
|
||||
{
|
||||
if ($this->skip_whitespace_changes) $xhash[trim($from_lines[$xi])] = 1; else $xhash[$from_lines[$xi]] = 1;
|
||||
}
|
||||
|
||||
for ($yi = $skip; $yi < $n_to - $endskip; $yi++)
|
||||
{
|
||||
$line = ($this->skip_whitespace_changes) ? trim($to_lines[$yi]) : $to_lines[$yi];
|
||||
|
||||
if (($this->ychanged[$yi] = empty($xhash[$line])))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$yhash[$line] = 1;
|
||||
$this->yv[] = $line;
|
||||
$this->yind[] = $yi;
|
||||
}
|
||||
|
||||
for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
|
||||
{
|
||||
$line = ($this->skip_whitespace_changes) ? trim($from_lines[$xi]) : $from_lines[$xi];
|
||||
|
||||
if (($this->xchanged[$xi] = empty($yhash[$line])))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$this->xv[] = $line;
|
||||
$this->xind[] = $xi;
|
||||
}
|
||||
|
||||
// Find the LCS.
|
||||
$this->_compareseq(0, count($this->xv), 0, count($this->yv));
|
||||
|
||||
// Merge edits when possible.
|
||||
if ($this->skip_whitespace_changes)
|
||||
{
|
||||
$from_lines_clean = array_map('trim', $from_lines);
|
||||
$to_lines_clean = array_map('trim', $to_lines);
|
||||
|
||||
$this->_shift_boundaries($from_lines_clean, $this->xchanged, $this->ychanged);
|
||||
$this->_shift_boundaries($to_lines_clean, $this->ychanged, $this->xchanged);
|
||||
|
||||
unset($from_lines_clean, $to_lines_clean);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged);
|
||||
$this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged);
|
||||
}
|
||||
|
||||
// Compute the edit operations.
|
||||
$edits = array();
|
||||
$xi = $yi = 0;
|
||||
|
||||
while ($xi < $n_from || $yi < $n_to)
|
||||
{
|
||||
// Skip matching "snake".
|
||||
$copy = array();
|
||||
|
||||
while ($xi < $n_from && $yi < $n_to && !$this->xchanged[$xi] && !$this->ychanged[$yi])
|
||||
{
|
||||
$copy[] = $from_lines[$xi++];
|
||||
$yi++;
|
||||
}
|
||||
|
||||
if ($copy)
|
||||
{
|
||||
$edits[] = new diff_op_copy($copy);
|
||||
}
|
||||
|
||||
// Find deletes & adds.
|
||||
$delete = array();
|
||||
while ($xi < $n_from && $this->xchanged[$xi])
|
||||
{
|
||||
$delete[] = $from_lines[$xi++];
|
||||
}
|
||||
|
||||
$add = array();
|
||||
while ($yi < $n_to && $this->ychanged[$yi])
|
||||
{
|
||||
$add[] = $to_lines[$yi++];
|
||||
}
|
||||
|
||||
if ($delete && $add)
|
||||
{
|
||||
$edits[] = new diff_op_change($delete, $add);
|
||||
}
|
||||
else if ($delete)
|
||||
{
|
||||
$edits[] = new diff_op_delete($delete);
|
||||
}
|
||||
else if ($add)
|
||||
{
|
||||
$edits[] = new diff_op_add($add);
|
||||
}
|
||||
}
|
||||
|
||||
return $edits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Divides the Largest Common Subsequence (LCS) of the sequences (XOFF,
|
||||
* XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized segments.
|
||||
*
|
||||
* Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of
|
||||
* NCHUNKS+1 (X, Y) indexes giving the diving points between sub
|
||||
* sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1),
|
||||
* the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) ==
|
||||
* (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
|
||||
*
|
||||
* This function assumes that the first lines of the specified portions of
|
||||
* the two files do not match, and likewise that the last lines do not
|
||||
* match. The caller must trim matching lines from the beginning and end
|
||||
* of the portions it is going to specify.
|
||||
*/
|
||||
function _diag($xoff, $xlim, $yoff, $ylim, $nchunks)
|
||||
{
|
||||
$flip = false;
|
||||
|
||||
if ($xlim - $xoff > $ylim - $yoff)
|
||||
{
|
||||
// Things seems faster (I'm not sure I understand why) when the shortest sequence is in X.
|
||||
$flip = true;
|
||||
list($xoff, $xlim, $yoff, $ylim) = array($yoff, $ylim, $xoff, $xlim);
|
||||
}
|
||||
|
||||
if ($flip)
|
||||
{
|
||||
for ($i = $ylim - 1; $i >= $yoff; $i--)
|
||||
{
|
||||
$ymatches[$this->xv[$i]][] = $i;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for ($i = $ylim - 1; $i >= $yoff; $i--)
|
||||
{
|
||||
$ymatches[$this->yv[$i]][] = $i;
|
||||
}
|
||||
}
|
||||
|
||||
$this->lcs = 0;
|
||||
$this->seq[0]= $yoff - 1;
|
||||
$this->in_seq = array();
|
||||
$ymids[0] = array();
|
||||
|
||||
$numer = $xlim - $xoff + $nchunks - 1;
|
||||
$x = $xoff;
|
||||
|
||||
for ($chunk = 0; $chunk < $nchunks; $chunk++)
|
||||
{
|
||||
if ($chunk > 0)
|
||||
{
|
||||
for ($i = 0; $i <= $this->lcs; $i++)
|
||||
{
|
||||
$ymids[$i][$chunk - 1] = $this->seq[$i];
|
||||
}
|
||||
}
|
||||
|
||||
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks);
|
||||
|
||||
for (; $x < $x1; $x++)
|
||||
{
|
||||
$line = $flip ? $this->yv[$x] : $this->xv[$x];
|
||||
if (empty($ymatches[$line]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$matches = $ymatches[$line];
|
||||
|
||||
reset($matches);
|
||||
while (list(, $y) = each($matches))
|
||||
{
|
||||
if (empty($this->in_seq[$y]))
|
||||
{
|
||||
$k = $this->_lcs_pos($y);
|
||||
$ymids[$k] = $ymids[$k - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// no reset() here
|
||||
while (list(, $y) = each($matches))
|
||||
{
|
||||
if ($y > $this->seq[$k - 1])
|
||||
{
|
||||
// Optimization: this is a common case: next match is just replacing previous match.
|
||||
$this->in_seq[$this->seq[$k]] = false;
|
||||
$this->seq[$k] = $y;
|
||||
$this->in_seq[$y] = 1;
|
||||
}
|
||||
else if (empty($this->in_seq[$y]))
|
||||
{
|
||||
$k = $this->_lcs_pos($y);
|
||||
$ymids[$k] = $ymids[$k - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff);
|
||||
$ymid = $ymids[$this->lcs];
|
||||
|
||||
for ($n = 0; $n < $nchunks - 1; $n++)
|
||||
{
|
||||
$x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks);
|
||||
$y1 = $ymid[$n] + 1;
|
||||
$seps[] = $flip ? array($y1, $x1) : array($x1, $y1);
|
||||
}
|
||||
$seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim);
|
||||
|
||||
return array($this->lcs, $seps);
|
||||
}
|
||||
|
||||
function _lcs_pos($ypos)
|
||||
{
|
||||
$end = $this->lcs;
|
||||
|
||||
if ($end == 0 || $ypos > $this->seq[$end])
|
||||
{
|
||||
$this->seq[++$this->lcs] = $ypos;
|
||||
$this->in_seq[$ypos] = 1;
|
||||
return $this->lcs;
|
||||
}
|
||||
|
||||
$beg = 1;
|
||||
while ($beg < $end)
|
||||
{
|
||||
$mid = (int)(($beg + $end) / 2);
|
||||
if ($ypos > $this->seq[$mid])
|
||||
{
|
||||
$beg = $mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$end = $mid;
|
||||
}
|
||||
}
|
||||
|
||||
$this->in_seq[$this->seq[$end]] = false;
|
||||
$this->seq[$end] = $ypos;
|
||||
$this->in_seq[$ypos] = 1;
|
||||
|
||||
return $end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds LCS of two sequences.
|
||||
*
|
||||
* The results are recorded in the vectors $this->{x,y}changed[], by
|
||||
* storing a 1 in the element for each line that is an insertion or
|
||||
* deletion (ie. is not in the LCS).
|
||||
*
|
||||
* The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1.
|
||||
*
|
||||
* Note that XLIM, YLIM are exclusive bounds. All line numbers are
|
||||
* origin-0 and discarded lines are not counted.
|
||||
*/
|
||||
function _compareseq($xoff, $xlim, $yoff, $ylim)
|
||||
{
|
||||
// Slide down the bottom initial diagonal.
|
||||
while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff])
|
||||
{
|
||||
++$xoff;
|
||||
++$yoff;
|
||||
}
|
||||
|
||||
// Slide up the top initial diagonal.
|
||||
while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1])
|
||||
{
|
||||
--$xlim;
|
||||
--$ylim;
|
||||
}
|
||||
|
||||
if ($xoff == $xlim || $yoff == $ylim)
|
||||
{
|
||||
$lcs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is ad hoc but seems to work well.
|
||||
// $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
|
||||
// $nchunks = max(2,min(8,(int)$nchunks));
|
||||
$nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1;
|
||||
list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks);
|
||||
}
|
||||
|
||||
if ($lcs == 0)
|
||||
{
|
||||
// X and Y sequences have no common subsequence: mark all changed.
|
||||
while ($yoff < $ylim)
|
||||
{
|
||||
$this->ychanged[$this->yind[$yoff++]] = 1;
|
||||
}
|
||||
|
||||
while ($xoff < $xlim)
|
||||
{
|
||||
$this->xchanged[$this->xind[$xoff++]] = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the partitions to split this problem into subproblems.
|
||||
reset($seps);
|
||||
$pt1 = $seps[0];
|
||||
|
||||
while ($pt2 = next($seps))
|
||||
{
|
||||
$this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]);
|
||||
$pt1 = $pt2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjusts inserts/deletes of identical lines to join changes as much as possible.
|
||||
*
|
||||
* We do something when a run of changed lines include a line at one end
|
||||
* and has an excluded, identical line at the other. We are free to
|
||||
* choose which identical line is included. 'compareseq' usually chooses
|
||||
* the one at the beginning, but usually it is cleaner to consider the
|
||||
* following identical line to be the "change".
|
||||
*
|
||||
* This is extracted verbatim from analyze.c (GNU diffutils-2.7).
|
||||
*/
|
||||
function _shift_boundaries($lines, &$changed, $other_changed)
|
||||
{
|
||||
$i = 0;
|
||||
$j = 0;
|
||||
|
||||
$len = count($lines);
|
||||
$other_len = count($other_changed);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Scan forward to find the beginning of another run of
|
||||
// changes. Also keep track of the corresponding point in the other file.
|
||||
//
|
||||
// Throughout this code, $i and $j are adjusted together so that
|
||||
// the first $i elements of $changed and the first $j elements of
|
||||
// $other_changed both contain the same number of zeros (unchanged lines).
|
||||
//
|
||||
// Furthermore, $j is always kept so that $j == $other_len or $other_changed[$j] == false.
|
||||
while ($j < $other_len && $other_changed[$j])
|
||||
{
|
||||
$j++;
|
||||
}
|
||||
|
||||
while ($i < $len && ! $changed[$i])
|
||||
{
|
||||
$i++;
|
||||
$j++;
|
||||
|
||||
while ($j < $other_len && $other_changed[$j])
|
||||
{
|
||||
$j++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($i == $len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$start = $i;
|
||||
|
||||
// Find the end of this run of changes.
|
||||
while (++$i < $len && $changed[$i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Record the length of this run of changes, so that we can later determine whether the run has grown.
|
||||
$runlength = $i - $start;
|
||||
|
||||
// Move the changed region back, so long as the previous unchanged line matches the last changed one.
|
||||
// This merges with previous changed regions.
|
||||
while ($start > 0 && $lines[$start - 1] == $lines[$i - 1])
|
||||
{
|
||||
$changed[--$start] = 1;
|
||||
$changed[--$i] = false;
|
||||
|
||||
while ($start > 0 && $changed[$start - 1])
|
||||
{
|
||||
$start--;
|
||||
}
|
||||
|
||||
while ($other_changed[--$j])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Set CORRESPONDING to the end of the changed run, at the last point where it corresponds to a changed run in the
|
||||
// other file. CORRESPONDING == LEN means no such point has been found.
|
||||
$corresponding = $j < $other_len ? $i : $len;
|
||||
|
||||
// Move the changed region forward, so long as the first changed line matches the following unchanged one.
|
||||
// This merges with following changed regions.
|
||||
// Do this second, so that if there are no merges, the changed region is moved forward as far as possible.
|
||||
while ($i < $len && $lines[$start] == $lines[$i])
|
||||
{
|
||||
$changed[$start++] = false;
|
||||
$changed[$i++] = 1;
|
||||
|
||||
while ($i < $len && $changed[$i])
|
||||
{
|
||||
$i++;
|
||||
}
|
||||
|
||||
$j++;
|
||||
if ($j < $other_len && $other_changed[$j])
|
||||
{
|
||||
$corresponding = $i;
|
||||
while ($j < $other_len && $other_changed[$j])
|
||||
{
|
||||
$j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while ($runlength != $i - $start);
|
||||
|
||||
// If possible, move the fully-merged run of changes back to a corresponding run in the other file.
|
||||
while ($corresponding < $i)
|
||||
{
|
||||
$changed[--$start] = 1;
|
||||
$changed[--$i] = 0;
|
||||
|
||||
while ($other_changed[--$j])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
861
includes/diff/renderer.php
Normal file
861
includes/diff/renderer.php
Normal file
@@ -0,0 +1,861 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Code from pear.php.net, Text_Diff-1.1.0 package
|
||||
* http://pear.php.net/package/Text_Diff/
|
||||
*
|
||||
* Modified by phpBB Limited to meet our coding standards
|
||||
* and being able to integrate into phpBB
|
||||
*
|
||||
* A class to render Diffs in different formats.
|
||||
*
|
||||
* This class renders the diff in classic diff format. It is intended that
|
||||
* this class be customized via inheritance, to obtain fancier outputs.
|
||||
*
|
||||
* Copyright 2004-2008 The Horde Project (http://www.horde.org/)
|
||||
*
|
||||
* @package diff
|
||||
*/
|
||||
class diff_renderer
|
||||
{
|
||||
/**
|
||||
* Number of leading context "lines" to preserve.
|
||||
*
|
||||
* This should be left at zero for this class, but subclasses may want to
|
||||
* set this to other values.
|
||||
*/
|
||||
var $_leading_context_lines = 0;
|
||||
|
||||
/**
|
||||
* Number of trailing context "lines" to preserve.
|
||||
*
|
||||
* This should be left at zero for this class, but subclasses may want to
|
||||
* set this to other values.
|
||||
*/
|
||||
var $_trailing_context_lines = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
function __construct($params = array())
|
||||
{
|
||||
foreach ($params as $param => $value)
|
||||
{
|
||||
$v = '_' . $param;
|
||||
if (isset($this->$v))
|
||||
{
|
||||
$this->$v = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any renderer parameters.
|
||||
*
|
||||
* @return array All parameters of this renderer object.
|
||||
*/
|
||||
function get_params()
|
||||
{
|
||||
$params = array();
|
||||
foreach (get_object_vars($this) as $k => $v)
|
||||
{
|
||||
if ($k[0] == '_')
|
||||
{
|
||||
$params[substr($k, 1)] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a diff.
|
||||
*
|
||||
* @param diff &$diff A diff object.
|
||||
*
|
||||
* @return string The formatted output.
|
||||
*/
|
||||
function render(&$diff)
|
||||
{
|
||||
$xi = $yi = 1;
|
||||
$block = false;
|
||||
$context = array();
|
||||
|
||||
// Create a new diff object if it is a 3-way diff
|
||||
if (is_a($diff, 'diff3'))
|
||||
{
|
||||
$diff3 = &$diff;
|
||||
|
||||
$diff_1 = $diff3->get_original();
|
||||
$diff_2 = $diff3->merged_output();
|
||||
|
||||
unset($diff3);
|
||||
|
||||
$diff = new diff($diff_1, $diff_2);
|
||||
}
|
||||
|
||||
$nlead = $this->_leading_context_lines;
|
||||
$ntrail = $this->_trailing_context_lines;
|
||||
|
||||
$output = $this->_start_diff();
|
||||
$diffs = $diff->get_diff();
|
||||
|
||||
foreach ($diffs as $i => $edit)
|
||||
{
|
||||
// If these are unchanged (copied) lines, and we want to keep leading or trailing context lines, extract them from the copy block.
|
||||
if (is_a($edit, 'diff_op_copy'))
|
||||
{
|
||||
// Do we have any diff blocks yet?
|
||||
if (is_array($block))
|
||||
{
|
||||
// How many lines to keep as context from the copy block.
|
||||
$keep = ($i == count($diffs) - 1) ? $ntrail : $nlead + $ntrail;
|
||||
if (count($edit->orig) <= $keep)
|
||||
{
|
||||
// We have less lines in the block than we want for context => keep the whole block.
|
||||
$block[] = $edit;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($ntrail)
|
||||
{
|
||||
// Create a new block with as many lines as we need for the trailing context.
|
||||
$context = array_slice($edit->orig, 0, $ntrail);
|
||||
$block[] = new diff_op_copy($context);
|
||||
}
|
||||
|
||||
$output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block);
|
||||
$block = false;
|
||||
}
|
||||
}
|
||||
// Keep the copy block as the context for the next block.
|
||||
$context = $edit->orig;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't we have any diff blocks yet?
|
||||
if (!is_array($block))
|
||||
{
|
||||
// Extract context lines from the preceding copy block.
|
||||
$context = array_slice($context, count($context) - $nlead);
|
||||
$x0 = $xi - count($context);
|
||||
$y0 = $yi - count($context);
|
||||
$block = array();
|
||||
|
||||
if ($context)
|
||||
{
|
||||
$block[] = new diff_op_copy($context);
|
||||
}
|
||||
}
|
||||
$block[] = $edit;
|
||||
}
|
||||
|
||||
$xi += ($edit->orig) ? count($edit->orig) : 0;
|
||||
$yi += ($edit->final) ? count($edit->final) : 0;
|
||||
}
|
||||
|
||||
if (is_array($block))
|
||||
{
|
||||
$output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block);
|
||||
}
|
||||
|
||||
return $output . $this->_end_diff();
|
||||
}
|
||||
|
||||
function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
|
||||
{
|
||||
$output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen));
|
||||
|
||||
foreach ($edits as $edit)
|
||||
{
|
||||
switch (get_class($edit))
|
||||
{
|
||||
case 'diff_op_copy':
|
||||
$output .= $this->_context($edit->orig);
|
||||
break;
|
||||
|
||||
case 'diff_op_add':
|
||||
$output .= $this->_added($edit->final);
|
||||
break;
|
||||
|
||||
case 'diff_op_delete':
|
||||
$output .= $this->_deleted($edit->orig);
|
||||
break;
|
||||
|
||||
case 'diff_op_change':
|
||||
$output .= $this->_changed($edit->orig, $edit->final);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $output . $this->_end_block();
|
||||
}
|
||||
|
||||
function _start_diff()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _end_diff()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _block_header($xbeg, $xlen, $ybeg, $ylen)
|
||||
{
|
||||
if ($xlen > 1)
|
||||
{
|
||||
$xbeg .= ',' . ($xbeg + $xlen - 1);
|
||||
}
|
||||
|
||||
if ($ylen > 1)
|
||||
{
|
||||
$ybeg .= ',' . ($ybeg + $ylen - 1);
|
||||
}
|
||||
|
||||
// this matches the GNU Diff behaviour
|
||||
if ($xlen && !$ylen)
|
||||
{
|
||||
$ybeg--;
|
||||
}
|
||||
else if (!$xlen)
|
||||
{
|
||||
$xbeg--;
|
||||
}
|
||||
|
||||
return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
|
||||
}
|
||||
|
||||
function _start_block($header)
|
||||
{
|
||||
return $header . "\n";
|
||||
}
|
||||
|
||||
function _end_block()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _lines($lines, $prefix = ' ')
|
||||
{
|
||||
return $prefix . implode("\n$prefix", $lines) . "\n";
|
||||
}
|
||||
|
||||
function _context($lines)
|
||||
{
|
||||
return $this->_lines($lines, ' ');
|
||||
}
|
||||
|
||||
function _added($lines)
|
||||
{
|
||||
return $this->_lines($lines, '> ');
|
||||
}
|
||||
|
||||
function _deleted($lines)
|
||||
{
|
||||
return $this->_lines($lines, '< ');
|
||||
}
|
||||
|
||||
function _changed($orig, $final)
|
||||
{
|
||||
return $this->_deleted($orig) . "---\n" . $this->_added($final);
|
||||
}
|
||||
|
||||
/**
|
||||
* Our function to get the diff
|
||||
*/
|
||||
function get_diff_content($diff)
|
||||
{
|
||||
return $this->render($diff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a unified diff
|
||||
* @package diff
|
||||
*/
|
||||
class diff_renderer_unified extends diff_renderer
|
||||
{
|
||||
var $_leading_context_lines = 4;
|
||||
var $_trailing_context_lines = 4;
|
||||
|
||||
/**
|
||||
* Our function to get the diff
|
||||
*/
|
||||
function get_diff_content($diff)
|
||||
{
|
||||
return nl2br($this->render($diff));
|
||||
}
|
||||
|
||||
function _block_header($xbeg, $xlen, $ybeg, $ylen)
|
||||
{
|
||||
if ($xlen != 1)
|
||||
{
|
||||
$xbeg .= ',' . $xlen;
|
||||
}
|
||||
|
||||
if ($ylen != 1)
|
||||
{
|
||||
$ybeg .= ',' . $ylen;
|
||||
}
|
||||
return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>';
|
||||
}
|
||||
|
||||
function _context($lines)
|
||||
{
|
||||
return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>';
|
||||
}
|
||||
|
||||
function _added($lines)
|
||||
{
|
||||
return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>';
|
||||
}
|
||||
|
||||
function _deleted($lines)
|
||||
{
|
||||
return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>';
|
||||
}
|
||||
|
||||
function _changed($orig, $final)
|
||||
{
|
||||
return $this->_deleted($orig) . $this->_added($final);
|
||||
}
|
||||
|
||||
function _start_diff()
|
||||
{
|
||||
$start = '<div class="file">';
|
||||
|
||||
return $start;
|
||||
}
|
||||
|
||||
function _end_diff()
|
||||
{
|
||||
return '</div>';
|
||||
}
|
||||
|
||||
function _end_block()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "Inline" diff renderer.
|
||||
*
|
||||
* This class renders diffs in the Wiki-style "inline" format.
|
||||
*
|
||||
* @author Ciprian Popovici
|
||||
* @package diff
|
||||
*/
|
||||
class diff_renderer_inline extends diff_renderer
|
||||
{
|
||||
var $_leading_context_lines = 10000;
|
||||
var $_trailing_context_lines = 10000;
|
||||
|
||||
// Prefix and suffix for inserted text
|
||||
var $_ins_prefix = '<span class="ins">';
|
||||
var $_ins_suffix = '</span>';
|
||||
|
||||
// Prefix and suffix for deleted text
|
||||
var $_del_prefix = '<span class="del">';
|
||||
var $_del_suffix = '</span>';
|
||||
|
||||
var $_block_head = '';
|
||||
|
||||
// What are we currently splitting on? Used to recurse to show word-level
|
||||
var $_split_level = 'lines';
|
||||
|
||||
/**
|
||||
* Our function to get the diff
|
||||
*/
|
||||
function get_diff_content($diff)
|
||||
{
|
||||
return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>';
|
||||
}
|
||||
|
||||
function _start_diff()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _end_diff()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
function _block_header($xbeg, $xlen, $ybeg, $ylen)
|
||||
{
|
||||
return $this->_block_head;
|
||||
}
|
||||
|
||||
function _start_block($header)
|
||||
{
|
||||
return $header;
|
||||
}
|
||||
|
||||
function _lines($lines, $prefix = ' ', $encode = true)
|
||||
{
|
||||
if ($encode)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_encode'));
|
||||
}
|
||||
|
||||
if ($this->_split_level == 'words')
|
||||
{
|
||||
return implode('', $lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
return implode("\n", $lines) . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
function _added($lines)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_encode'));
|
||||
$lines[0] = $this->_ins_prefix . $lines[0];
|
||||
$lines[count($lines) - 1] .= $this->_ins_suffix;
|
||||
return $this->_lines($lines, ' ', false);
|
||||
}
|
||||
|
||||
function _deleted($lines, $words = false)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_encode'));
|
||||
$lines[0] = $this->_del_prefix . $lines[0];
|
||||
$lines[count($lines) - 1] .= $this->_del_suffix;
|
||||
return $this->_lines($lines, ' ', false);
|
||||
}
|
||||
|
||||
function _changed($orig, $final)
|
||||
{
|
||||
// If we've already split on words, don't try to do so again - just display.
|
||||
if ($this->_split_level == 'words')
|
||||
{
|
||||
$prefix = '';
|
||||
while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ')
|
||||
{
|
||||
$prefix .= substr($orig[0], 0, 1);
|
||||
$orig[0] = substr($orig[0], 1);
|
||||
$final[0] = substr($final[0], 1);
|
||||
}
|
||||
|
||||
return $prefix . $this->_deleted($orig) . $this->_added($final);
|
||||
}
|
||||
|
||||
$text1 = implode("\n", $orig);
|
||||
$text2 = implode("\n", $final);
|
||||
|
||||
// Non-printing newline marker.
|
||||
$nl = "\0";
|
||||
|
||||
// We want to split on word boundaries, but we need to preserve whitespace as well.
|
||||
// Therefore we split on words, but include all blocks of whitespace in the wordlist.
|
||||
$splitted_text_1 = $this->_split_on_words($text1, $nl);
|
||||
$splitted_text_2 = $this->_split_on_words($text2, $nl);
|
||||
|
||||
$diff = new diff($splitted_text_1, $splitted_text_2);
|
||||
unset($splitted_text_1, $splitted_text_2);
|
||||
|
||||
// Get the diff in inline format.
|
||||
$renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words')));
|
||||
|
||||
// Run the diff and get the output.
|
||||
return str_replace($nl, "\n", $renderer->render($diff)) . "\n";
|
||||
}
|
||||
|
||||
function _split_on_words($string, $newline_escape = "\n")
|
||||
{
|
||||
// Ignore \0; otherwise the while loop will never finish.
|
||||
$string = str_replace("\0", '', $string);
|
||||
|
||||
$words = array();
|
||||
$length = strlen($string);
|
||||
$pos = 0;
|
||||
|
||||
$tab_there = true;
|
||||
while ($pos < $length)
|
||||
{
|
||||
// Check for tabs... do not include them
|
||||
if ($tab_there && substr($string, $pos, 1) === "\t")
|
||||
{
|
||||
$words[] = "\t";
|
||||
$pos++;
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tab_there = false;
|
||||
}
|
||||
|
||||
// Eat a word with any preceding whitespace.
|
||||
$spaces = strspn(substr($string, $pos), " \n");
|
||||
$nextpos = strcspn(substr($string, $pos + $spaces), " \n");
|
||||
$words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos));
|
||||
$pos += $spaces + $nextpos;
|
||||
}
|
||||
|
||||
return $words;
|
||||
}
|
||||
|
||||
function _encode(&$string)
|
||||
{
|
||||
$string = htmlspecialchars($string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "raw" diff renderer.
|
||||
* This class could be used to output a raw unified patch file
|
||||
*
|
||||
* @package diff
|
||||
*/
|
||||
class diff_renderer_raw extends diff_renderer
|
||||
{
|
||||
var $_leading_context_lines = 4;
|
||||
var $_trailing_context_lines = 4;
|
||||
|
||||
/**
|
||||
* Our function to get the diff
|
||||
*/
|
||||
function get_diff_content($diff)
|
||||
{
|
||||
return '<textarea style="height: 290px;" rows="15" cols="76" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>';
|
||||
}
|
||||
|
||||
function _block_header($xbeg, $xlen, $ybeg, $ylen)
|
||||
{
|
||||
if ($xlen != 1)
|
||||
{
|
||||
$xbeg .= ',' . $xlen;
|
||||
}
|
||||
|
||||
if ($ylen != 1)
|
||||
{
|
||||
$ybeg .= ',' . $ylen;
|
||||
}
|
||||
return '@@ -' . $xbeg . ' +' . $ybeg . ' @@';
|
||||
}
|
||||
|
||||
function _context($lines)
|
||||
{
|
||||
return $this->_lines($lines, ' ');
|
||||
}
|
||||
|
||||
function _added($lines)
|
||||
{
|
||||
return $this->_lines($lines, '+');
|
||||
}
|
||||
|
||||
function _deleted($lines)
|
||||
{
|
||||
return $this->_lines($lines, '-');
|
||||
}
|
||||
|
||||
function _changed($orig, $final)
|
||||
{
|
||||
return $this->_deleted($orig) . $this->_added($final);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "chora (Horde)" diff renderer - similar style.
|
||||
* This renderer class is a modified human_readable function from the Horde Framework.
|
||||
*
|
||||
* @package diff
|
||||
*/
|
||||
class diff_renderer_side_by_side extends diff_renderer
|
||||
{
|
||||
var $_leading_context_lines = 3;
|
||||
var $_trailing_context_lines = 3;
|
||||
|
||||
var $lines = array();
|
||||
|
||||
// Hold the left and right columns of lines for change blocks.
|
||||
var $cols;
|
||||
var $state;
|
||||
|
||||
var $data = false;
|
||||
|
||||
/**
|
||||
* Our function to get the diff
|
||||
*/
|
||||
function get_diff_content($diff)
|
||||
{
|
||||
global $user;
|
||||
|
||||
$output = '';
|
||||
$output .= '<table cellspacing="0" class="hrdiff">
|
||||
<caption>
|
||||
<span class="unmodified"> </span> ' . $user->lang['LINE_UNMODIFIED'] . '
|
||||
<span class="added"> </span> ' . $user->lang['LINE_ADDED'] . '
|
||||
<span class="modified"> </span> ' . $user->lang['LINE_MODIFIED'] . '
|
||||
<span class="removed"> </span> ' . $user->lang['LINE_REMOVED'] . '
|
||||
</caption>
|
||||
<tbody>
|
||||
';
|
||||
|
||||
$this->render($diff);
|
||||
|
||||
// Is the diff empty?
|
||||
if (!count($this->lines))
|
||||
{
|
||||
$output .= '<tr><th colspan="2">' . $user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>';
|
||||
}
|
||||
else
|
||||
{
|
||||
// Iterate through every header block of changes
|
||||
foreach ($this->lines as $header)
|
||||
{
|
||||
$output .= '<tr><th>' . $user->lang['LINE'] . ' ' . $header['oldline'] . '</th><th>' . $user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>';
|
||||
|
||||
// Each header block consists of a number of changes (add, remove, change).
|
||||
$current_context = '';
|
||||
|
||||
foreach ($header['contents'] as $change)
|
||||
{
|
||||
if (!empty($current_context) && $change['type'] != 'empty')
|
||||
{
|
||||
$line = $current_context;
|
||||
$current_context = '';
|
||||
|
||||
$output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td>
|
||||
<td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>';
|
||||
}
|
||||
|
||||
switch ($change['type'])
|
||||
{
|
||||
case 'add':
|
||||
$line = '';
|
||||
|
||||
foreach ($change['lines'] as $_line)
|
||||
{
|
||||
$line .= htmlspecialchars($_line) . '<br />';
|
||||
}
|
||||
|
||||
$output .= '<tr><td class="added_empty"> </td><td class="added"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>';
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
$line = '';
|
||||
|
||||
foreach ($change['lines'] as $_line)
|
||||
{
|
||||
$line .= htmlspecialchars($_line) . '<br />';
|
||||
}
|
||||
|
||||
$output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td><td class="removed_empty"> </td></tr>';
|
||||
break;
|
||||
|
||||
case 'empty':
|
||||
$current_context .= htmlspecialchars($change['line']) . '<br />';
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
// Pop the old/new stacks one by one, until both are empty.
|
||||
$oldsize = count($change['old']);
|
||||
$newsize = count($change['new']);
|
||||
$left = $right = '';
|
||||
|
||||
for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row)
|
||||
{
|
||||
$left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : '';
|
||||
$left .= '<br />';
|
||||
$right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : '';
|
||||
$right .= '<br />';
|
||||
}
|
||||
|
||||
$output .= '<tr>';
|
||||
|
||||
if (!empty($left))
|
||||
{
|
||||
$output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>';
|
||||
}
|
||||
else if ($row < $oldsize)
|
||||
{
|
||||
$output .= '<td class="modified"> </td>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= '<td class="unmodified"> </td>';
|
||||
}
|
||||
|
||||
if (!empty($right))
|
||||
{
|
||||
$output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>';
|
||||
}
|
||||
else if ($row < $newsize)
|
||||
{
|
||||
$output .= '<td class="modified"> </td>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$output .= '<td class="unmodified"> </td>';
|
||||
}
|
||||
|
||||
$output .= '</tr>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($current_context))
|
||||
{
|
||||
$line = $current_context;
|
||||
$current_context = '';
|
||||
|
||||
$output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td>';
|
||||
$output .= '<td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '</tbody></table>';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
function _start_diff()
|
||||
{
|
||||
$this->lines = array();
|
||||
|
||||
$this->data = false;
|
||||
$this->cols = array(array(), array());
|
||||
$this->state = 'empty';
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function _end_diff()
|
||||
{
|
||||
// Just flush any remaining entries in the columns stack.
|
||||
switch ($this->state)
|
||||
{
|
||||
case 'add':
|
||||
$this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
// We have some removal lines pending in our stack, so flush them.
|
||||
$this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
// We have both remove and addition lines, so this is a change block.
|
||||
$this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->data !== false)
|
||||
{
|
||||
$this->lines[] = $this->data;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
function _block_header($xbeg, $xlen, $ybeg, $ylen)
|
||||
{
|
||||
// Push any previous header information to the return stack.
|
||||
if ($this->data !== false)
|
||||
{
|
||||
$this->lines[] = $this->data;
|
||||
}
|
||||
|
||||
$this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array());
|
||||
$this->state = 'dump';
|
||||
}
|
||||
|
||||
function _added($lines)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_perform_add'));
|
||||
}
|
||||
|
||||
function _perform_add($line)
|
||||
{
|
||||
if ($this->state == 'empty')
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
// This is just an addition line.
|
||||
if ($this->state == 'dump' || $this->state == 'add')
|
||||
{
|
||||
// Start adding to the addition stack.
|
||||
$this->cols[0][] = $line;
|
||||
$this->state = 'add';
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is inside a change block, so start accumulating lines.
|
||||
$this->state = 'change';
|
||||
$this->cols[1][] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
function _deleted($lines)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_perform_delete'));
|
||||
}
|
||||
|
||||
function _perform_delete($line)
|
||||
{
|
||||
// This is a removal line.
|
||||
$this->state = 'remove';
|
||||
$this->cols[0][] = $line;
|
||||
}
|
||||
|
||||
function _context($lines)
|
||||
{
|
||||
array_walk($lines, array(&$this, '_perform_context'));
|
||||
}
|
||||
|
||||
function _perform_context($line)
|
||||
{
|
||||
// An empty block with no action.
|
||||
switch ($this->state)
|
||||
{
|
||||
case 'add':
|
||||
$this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
// We have some removal lines pending in our stack, so flush them.
|
||||
$this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]);
|
||||
break;
|
||||
|
||||
case 'change':
|
||||
// We have both remove and addition lines, so this is a change block.
|
||||
$this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->cols = array(array(), array());
|
||||
$this->data['contents'][] = array('type' => 'empty', 'line' => $line);
|
||||
$this->state = 'dump';
|
||||
}
|
||||
|
||||
function _changed($orig, $final)
|
||||
{
|
||||
return $this->_deleted($orig) . $this->_added($final);
|
||||
}
|
||||
|
||||
}
|
||||
4947
includes/functions.php
Normal file
4947
includes/functions.php
Normal file
File diff suppressed because it is too large
Load Diff
726
includes/functions_acp.php
Normal file
726
includes/functions_acp.php
Normal file
@@ -0,0 +1,726 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Header for acp pages
|
||||
*/
|
||||
function adm_page_header($page_title)
|
||||
{
|
||||
global $config, $user, $template;
|
||||
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $SID, $_SID;
|
||||
global $phpbb_dispatcher, $phpbb_container;
|
||||
|
||||
if (defined('HEADER_INC'))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
define('HEADER_INC', true);
|
||||
|
||||
// A listener can set this variable to `true` when it overrides this function
|
||||
$adm_page_header_override = false;
|
||||
|
||||
/**
|
||||
* Execute code and/or overwrite adm_page_header()
|
||||
*
|
||||
* @event core.adm_page_header
|
||||
* @var string page_title Page title
|
||||
* @var bool adm_page_header_override Shall we return instead of
|
||||
* running the rest of adm_page_header()
|
||||
* @since 3.1.0-a1
|
||||
*/
|
||||
$vars = array('page_title', 'adm_page_header_override');
|
||||
extract($phpbb_dispatcher->trigger_event('core.adm_page_header', compact($vars)));
|
||||
|
||||
if ($adm_page_header_override)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$user->update_session_infos();
|
||||
|
||||
// gzip_compression
|
||||
if ($config['gzip_compress'])
|
||||
{
|
||||
if (@extension_loaded('zlib') && !headers_sent())
|
||||
{
|
||||
ob_start('ob_gzhandler');
|
||||
}
|
||||
}
|
||||
|
||||
$template->assign_vars(array(
|
||||
'PAGE_TITLE' => $page_title,
|
||||
'USERNAME' => $user->data['username'],
|
||||
|
||||
'SID' => $SID,
|
||||
'_SID' => $_SID,
|
||||
'SESSION_ID' => $user->session_id,
|
||||
'ROOT_PATH' => $phpbb_root_path,
|
||||
'ADMIN_ROOT_PATH' => $phpbb_admin_path,
|
||||
|
||||
'U_LOGOUT' => append_sid("{$phpbb_root_path}ucp.$phpEx", 'mode=logout'),
|
||||
'U_ADM_LOGOUT' => append_sid("{$phpbb_admin_path}index.$phpEx", 'action=admlogout'),
|
||||
'U_ADM_INDEX' => append_sid("{$phpbb_admin_path}index.$phpEx"),
|
||||
'U_INDEX' => append_sid("{$phpbb_root_path}index.$phpEx"),
|
||||
|
||||
'T_IMAGES_PATH' => "{$phpbb_root_path}images/",
|
||||
'T_SMILIES_PATH' => "{$phpbb_root_path}{$config['smilies_path']}/",
|
||||
'T_AVATAR_PATH' => "{$phpbb_root_path}{$config['avatar_path']}/",
|
||||
'T_AVATAR_GALLERY_PATH' => "{$phpbb_root_path}{$config['avatar_gallery_path']}/",
|
||||
'T_ICONS_PATH' => "{$phpbb_root_path}{$config['icons_path']}/",
|
||||
'T_RANKS_PATH' => "{$phpbb_root_path}{$config['ranks_path']}/",
|
||||
'T_UPLOAD_PATH' => "{$phpbb_root_path}{$config['upload_path']}/",
|
||||
'T_FONT_AWESOME_LINK' => !empty($config['allow_cdn']) && !empty($config['load_font_awesome_url']) ? $config['load_font_awesome_url'] : "{$phpbb_root_path}assets/css/font-awesome.min.css?assets_version=" . $config['assets_version'],
|
||||
|
||||
'T_ASSETS_VERSION' => $config['assets_version'],
|
||||
|
||||
'ICON_MOVE_UP' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />',
|
||||
'ICON_MOVE_UP_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_up_disabled.gif" alt="' . $user->lang['MOVE_UP'] . '" title="' . $user->lang['MOVE_UP'] . '" />',
|
||||
'ICON_MOVE_DOWN' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />',
|
||||
'ICON_MOVE_DOWN_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_down_disabled.gif" alt="' . $user->lang['MOVE_DOWN'] . '" title="' . $user->lang['MOVE_DOWN'] . '" />',
|
||||
'ICON_EDIT' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />',
|
||||
'ICON_EDIT_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_edit_disabled.gif" alt="' . $user->lang['EDIT'] . '" title="' . $user->lang['EDIT'] . '" />',
|
||||
'ICON_DELETE' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />',
|
||||
'ICON_DELETE_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_delete_disabled.gif" alt="' . $user->lang['DELETE'] . '" title="' . $user->lang['DELETE'] . '" />',
|
||||
'ICON_SYNC' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />',
|
||||
'ICON_SYNC_DISABLED' => '<img src="' . htmlspecialchars($phpbb_admin_path) . 'images/icon_sync_disabled.gif" alt="' . $user->lang['RESYNC'] . '" title="' . $user->lang['RESYNC'] . '" />',
|
||||
|
||||
'S_USER_LANG' => $user->lang['USER_LANG'],
|
||||
'S_CONTENT_DIRECTION' => $user->lang['DIRECTION'],
|
||||
'S_CONTENT_ENCODING' => 'UTF-8',
|
||||
'S_CONTENT_FLOW_BEGIN' => ($user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right',
|
||||
'S_CONTENT_FLOW_END' => ($user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left',
|
||||
|
||||
'CONTAINER_EXCEPTION' => $phpbb_container->hasParameter('container_exception') ? $phpbb_container->getParameter('container_exception') : false,
|
||||
));
|
||||
|
||||
// An array of http headers that phpbb will set. The following event may override these.
|
||||
$http_headers = array(
|
||||
// application/xhtml+xml not used because of IE
|
||||
'Content-type' => 'text/html; charset=UTF-8',
|
||||
'Cache-Control' => 'private, no-cache="set-cookie"',
|
||||
'Expires' => gmdate('D, d M Y H:i:s', time()) . ' GMT',
|
||||
);
|
||||
|
||||
/**
|
||||
* Execute code and/or overwrite _common_ template variables after they have been assigned.
|
||||
*
|
||||
* @event core.adm_page_header_after
|
||||
* @var string page_title Page title
|
||||
* @var array http_headers HTTP headers that should be set by phpbb
|
||||
*
|
||||
* @since 3.1.0-RC3
|
||||
*/
|
||||
$vars = array('page_title', 'http_headers');
|
||||
extract($phpbb_dispatcher->trigger_event('core.adm_page_header_after', compact($vars)));
|
||||
|
||||
foreach ($http_headers as $hname => $hval)
|
||||
{
|
||||
header((string) $hname . ': ' . (string) $hval);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page footer for acp pages
|
||||
*/
|
||||
function adm_page_footer($copyright_html = true)
|
||||
{
|
||||
global $db, $config, $template, $user, $auth;
|
||||
global $phpbb_root_path;
|
||||
global $request, $phpbb_dispatcher;
|
||||
|
||||
// A listener can set this variable to `true` when it overrides this function
|
||||
$adm_page_footer_override = false;
|
||||
|
||||
/**
|
||||
* Execute code and/or overwrite adm_page_footer()
|
||||
*
|
||||
* @event core.adm_page_footer
|
||||
* @var bool copyright_html Shall we display the copyright?
|
||||
* @var bool adm_page_footer_override Shall we return instead of
|
||||
* running the rest of adm_page_footer()
|
||||
* @since 3.1.0-a1
|
||||
*/
|
||||
$vars = array('copyright_html', 'adm_page_footer_override');
|
||||
extract($phpbb_dispatcher->trigger_event('core.adm_page_footer', compact($vars)));
|
||||
|
||||
if ($adm_page_footer_override)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
phpbb_check_and_display_sql_report($request, $auth, $db);
|
||||
|
||||
$template->assign_vars(array(
|
||||
'DEBUG_OUTPUT' => phpbb_generate_debug_output($db, $config, $auth, $user, $phpbb_dispatcher),
|
||||
'TRANSLATION_INFO' => (!empty($user->lang['TRANSLATION_INFO'])) ? $user->lang['TRANSLATION_INFO'] : '',
|
||||
'S_COPYRIGHT_HTML' => $copyright_html,
|
||||
'CREDIT_LINE' => $user->lang('POWERED_BY', '<a href="https://www.phpbb.com/">phpBB</a>® Forum Software © phpBB Limited'),
|
||||
'T_JQUERY_LINK' => !empty($config['allow_cdn']) && !empty($config['load_jquery_url']) ? $config['load_jquery_url'] : "{$phpbb_root_path}assets/javascript/jquery.min.js",
|
||||
'S_ALLOW_CDN' => !empty($config['allow_cdn']),
|
||||
'VERSION' => $config['version'])
|
||||
);
|
||||
|
||||
$template->display('body');
|
||||
|
||||
garbage_collection();
|
||||
exit_handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate back link for acp pages
|
||||
*/
|
||||
function adm_back_link($u_action)
|
||||
{
|
||||
global $user;
|
||||
return '<br /><br /><a href="' . $u_action . '">« ' . $user->lang['BACK_TO_PREV'] . '</a>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Build select field options in acp pages
|
||||
*/
|
||||
function build_select($option_ary, $option_default = false)
|
||||
{
|
||||
global $user;
|
||||
|
||||
$html = '';
|
||||
foreach ($option_ary as $value => $title)
|
||||
{
|
||||
$selected = ($option_default !== false && $value == $option_default) ? ' selected="selected"' : '';
|
||||
$html .= '<option value="' . $value . '"' . $selected . '>' . $user->lang[$title] . '</option>';
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build radio fields in acp pages
|
||||
*/
|
||||
function h_radio($name, $input_ary, $input_default = false, $id = false, $key = false, $separator = '')
|
||||
{
|
||||
global $user;
|
||||
|
||||
$html = '';
|
||||
$id_assigned = false;
|
||||
foreach ($input_ary as $value => $title)
|
||||
{
|
||||
$selected = ($input_default !== false && $value == $input_default) ? ' checked="checked"' : '';
|
||||
$html .= '<label><input type="radio" name="' . $name . '"' . (($id && !$id_assigned) ? ' id="' . $id . '"' : '') . ' value="' . $value . '"' . $selected . (($key) ? ' accesskey="' . $key . '"' : '') . ' class="radio" /> ' . $user->lang[$title] . '</label>' . $separator;
|
||||
$id_assigned = true;
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build configuration template for acp configuration pages
|
||||
*/
|
||||
function build_cfg_template($tpl_type, $key, &$new_ary, $config_key, $vars)
|
||||
{
|
||||
global $user, $module, $phpbb_dispatcher;
|
||||
|
||||
$tpl = '';
|
||||
$name = 'config[' . $config_key . ']';
|
||||
|
||||
// Make sure there is no notice printed out for non-existent config options (we simply set them)
|
||||
if (!isset($new_ary[$config_key]))
|
||||
{
|
||||
$new_ary[$config_key] = '';
|
||||
}
|
||||
|
||||
switch ($tpl_type[0])
|
||||
{
|
||||
case 'password':
|
||||
if ($new_ary[$config_key] !== '')
|
||||
{
|
||||
// replace passwords with asterixes
|
||||
$new_ary[$config_key] = '********';
|
||||
}
|
||||
case 'text':
|
||||
case 'url':
|
||||
case 'email':
|
||||
case 'tel':
|
||||
case 'search':
|
||||
// maxlength and size are only valid for these types and will be
|
||||
// ignored for other input types.
|
||||
$size = (int) $tpl_type[1];
|
||||
$maxlength = (int) $tpl_type[2];
|
||||
|
||||
$tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (($size) ? ' size="' . $size . '"' : '') . ' maxlength="' . (($maxlength) ? $maxlength : 255) . '" name="' . $name . '" value="' . $new_ary[$config_key] . '"' . (($tpl_type[0] === 'password') ? ' autocomplete="off"' : '') . ' />';
|
||||
break;
|
||||
|
||||
case 'color':
|
||||
case 'datetime':
|
||||
case 'datetime-local':
|
||||
case 'month':
|
||||
case 'week':
|
||||
$tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '" name="' . $name . '" value="' . $new_ary[$config_key] . '" />';
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
case 'time':
|
||||
case 'number':
|
||||
case 'range':
|
||||
$max = '';
|
||||
$min = ( isset($tpl_type[1]) ) ? (int) $tpl_type[1] : false;
|
||||
if ( isset($tpl_type[2]) )
|
||||
{
|
||||
$max = (int) $tpl_type[2];
|
||||
}
|
||||
|
||||
$tpl = '<input id="' . $key . '" type="' . $tpl_type[0] . '"' . (( $min != '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="' . $name . '" value="' . $new_ary[$config_key] . '" />';
|
||||
break;
|
||||
|
||||
case 'dimension':
|
||||
$max = '';
|
||||
|
||||
$min = (int) $tpl_type[1];
|
||||
|
||||
if ( isset($tpl_type[2]) )
|
||||
{
|
||||
$max = (int) $tpl_type[2];
|
||||
}
|
||||
|
||||
$tpl = '<input id="' . $key . '" type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_width]" value="' . $new_ary[$config_key . '_width'] . '" /> x <input type="number"' . (( $min !== '' ) ? ' min="' . $min . '"' : '') . (( $max != '' ) ? ' max="' . $max . '"' : '') . ' name="config[' . $config_key . '_height]" value="' . $new_ary[$config_key . '_height'] . '" />';
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
$rows = (int) $tpl_type[1];
|
||||
$cols = (int) $tpl_type[2];
|
||||
|
||||
$tpl = '<textarea id="' . $key . '" name="' . $name . '" rows="' . $rows . '" cols="' . $cols . '">' . $new_ary[$config_key] . '</textarea>';
|
||||
break;
|
||||
|
||||
case 'radio':
|
||||
$key_yes = ($new_ary[$config_key]) ? ' checked="checked"' : '';
|
||||
$key_no = (!$new_ary[$config_key]) ? ' checked="checked"' : '';
|
||||
|
||||
$tpl_type_cond = explode('_', $tpl_type[1]);
|
||||
$type_no = ($tpl_type_cond[0] == 'disabled' || $tpl_type_cond[0] == 'enabled') ? false : true;
|
||||
|
||||
$tpl_no = '<label><input type="radio" name="' . $name . '" value="0"' . $key_no . ' class="radio" /> ' . (($type_no) ? $user->lang['NO'] : $user->lang['DISABLED']) . '</label>';
|
||||
$tpl_yes = '<label><input type="radio" id="' . $key . '" name="' . $name . '" value="1"' . $key_yes . ' class="radio" /> ' . (($type_no) ? $user->lang['YES'] : $user->lang['ENABLED']) . '</label>';
|
||||
|
||||
$tpl = ($tpl_type_cond[0] == 'yes' || $tpl_type_cond[0] == 'enabled') ? $tpl_yes . $tpl_no : $tpl_no . $tpl_yes;
|
||||
break;
|
||||
|
||||
case 'select':
|
||||
case 'custom':
|
||||
|
||||
if (isset($vars['method']))
|
||||
{
|
||||
$call = array($module->module, $vars['method']);
|
||||
}
|
||||
else if (isset($vars['function']))
|
||||
{
|
||||
$call = $vars['function'];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($vars['params']))
|
||||
{
|
||||
$args = array();
|
||||
foreach ($vars['params'] as $value)
|
||||
{
|
||||
switch ($value)
|
||||
{
|
||||
case '{CONFIG_VALUE}':
|
||||
$value = $new_ary[$config_key];
|
||||
break;
|
||||
|
||||
case '{KEY}':
|
||||
$value = $key;
|
||||
break;
|
||||
}
|
||||
|
||||
$args[] = $value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$args = array($new_ary[$config_key], $key);
|
||||
}
|
||||
|
||||
$return = call_user_func_array($call, $args);
|
||||
|
||||
if ($tpl_type[0] == 'select')
|
||||
{
|
||||
$size = (isset($tpl_type[1])) ? (int) $tpl_type[1] : 1;
|
||||
$data_toggle = (!empty($tpl_type[2])) ? ' data-togglable-settings="true"' : '';
|
||||
|
||||
$tpl = '<select id="' . $key . '" name="' . $name . '"' . (($size > 1) ? ' size="' . $size . '"' : '') . $data_toggle . '>' . $return . '</select>';
|
||||
}
|
||||
else
|
||||
{
|
||||
$tpl = $return;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($vars['append']))
|
||||
{
|
||||
$tpl .= $vars['append'];
|
||||
}
|
||||
|
||||
$new = $new_ary;
|
||||
/**
|
||||
* Overwrite the html code we display for the config value
|
||||
*
|
||||
* @event core.build_config_template
|
||||
* @var array tpl_type Config type array:
|
||||
* 0 => data type
|
||||
* 1 [optional] => string: size, int: minimum
|
||||
* 2 [optional] => string: max. length, int: maximum
|
||||
* @var string key Should be used for the id attribute in html
|
||||
* @var array new Array with the config values we display
|
||||
* @var string name Should be used for the name attribute
|
||||
* @var array vars Array with the options for the config
|
||||
* @var string tpl The resulting html code we display
|
||||
* @since 3.1.0-a1
|
||||
*/
|
||||
$vars = array('tpl_type', 'key', 'new', 'name', 'vars', 'tpl');
|
||||
extract($phpbb_dispatcher->trigger_event('core.build_config_template', compact($vars)));
|
||||
$new_ary = $new;
|
||||
unset($new);
|
||||
|
||||
return $tpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Going through a config array and validate values, writing errors to $error. The validation method accepts parameters separated by ':' for string and int.
|
||||
* The first parameter defines the type to be used, the second the lower bound and the third the upper bound. Only the type is required.
|
||||
*/
|
||||
function validate_config_vars($config_vars, &$cfg_array, &$error)
|
||||
{
|
||||
global $phpbb_root_path, $user, $phpbb_dispatcher, $phpbb_filesystem, $language;
|
||||
|
||||
$type = 0;
|
||||
$min = 1;
|
||||
$max = 2;
|
||||
|
||||
foreach ($config_vars as $config_name => $config_definition)
|
||||
{
|
||||
if (!isset($cfg_array[$config_name]) || strpos($config_name, 'legend') !== false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($config_definition['validate']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$validator = explode(':', $config_definition['validate']);
|
||||
|
||||
// Validate a bit. ;) (0 = type, 1 = min, 2= max)
|
||||
switch ($validator[$type])
|
||||
{
|
||||
case 'url':
|
||||
$cfg_array[$config_name] = trim($cfg_array[$config_name]);
|
||||
|
||||
if (!empty($cfg_array[$config_name]) && !preg_match('#^' . get_preg_expression('url') . '$#iu', $cfg_array[$config_name]))
|
||||
{
|
||||
$error[] = $language->lang('URL_INVALID', $language->lang($config_definition['lang']));
|
||||
}
|
||||
|
||||
// no break here
|
||||
|
||||
case 'string':
|
||||
$length = utf8_strlen($cfg_array[$config_name]);
|
||||
|
||||
// the column is a VARCHAR
|
||||
$validator[$max] = (isset($validator[$max])) ? min(255, $validator[$max]) : 255;
|
||||
|
||||
if (isset($validator[$min]) && $length < $validator[$min])
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_SHORT'], $user->lang[$config_definition['lang']], $validator[$min]);
|
||||
}
|
||||
else if (isset($validator[$max]) && $length > $validator[2])
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_LONG'], $user->lang[$config_definition['lang']], $validator[$max]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'bool':
|
||||
$cfg_array[$config_name] = ($cfg_array[$config_name]) ? 1 : 0;
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
$cfg_array[$config_name] = (int) $cfg_array[$config_name];
|
||||
|
||||
if (isset($validator[$min]) && $cfg_array[$config_name] < $validator[$min])
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_LOW'], $user->lang[$config_definition['lang']], $validator[$min]);
|
||||
}
|
||||
else if (isset($validator[$max]) && $cfg_array[$config_name] > $validator[$max])
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_BIG'], $user->lang[$config_definition['lang']], $validator[$max]);
|
||||
}
|
||||
|
||||
if (strpos($config_name, '_max') !== false)
|
||||
{
|
||||
// Min/max pairs of settings should ensure that min <= max
|
||||
// Replace _max with _min to find the name of the minimum
|
||||
// corresponding configuration variable
|
||||
$min_name = str_replace('_max', '_min', $config_name);
|
||||
|
||||
if (isset($cfg_array[$min_name]) && is_numeric($cfg_array[$min_name]) && $cfg_array[$config_name] < $cfg_array[$min_name])
|
||||
{
|
||||
// A minimum value exists and the maximum value is less than it
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_LOW'], $user->lang[$config_definition['lang']], (int) $cfg_array[$min_name]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'email':
|
||||
if (!preg_match('/^' . get_preg_expression('email') . '$/i', $cfg_array[$config_name]))
|
||||
{
|
||||
$error[] = $user->lang['EMAIL_INVALID_EMAIL'];
|
||||
}
|
||||
break;
|
||||
|
||||
// Absolute path
|
||||
case 'script_path':
|
||||
if (!$cfg_array[$config_name])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$destination = str_replace('\\', '/', $cfg_array[$config_name]);
|
||||
|
||||
if ($destination !== '/')
|
||||
{
|
||||
// Adjust destination path (no trailing slash)
|
||||
if (substr($destination, -1, 1) == '/')
|
||||
{
|
||||
$destination = substr($destination, 0, -1);
|
||||
}
|
||||
|
||||
$destination = str_replace(array('../', './'), '', $destination);
|
||||
|
||||
if ($destination[0] != '/')
|
||||
{
|
||||
$destination = '/' . $destination;
|
||||
}
|
||||
}
|
||||
|
||||
$cfg_array[$config_name] = trim($destination);
|
||||
|
||||
break;
|
||||
|
||||
// Absolute path
|
||||
case 'lang':
|
||||
if (!$cfg_array[$config_name])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$cfg_array[$config_name] = basename($cfg_array[$config_name]);
|
||||
|
||||
if (!file_exists($phpbb_root_path . 'language/' . $cfg_array[$config_name] . '/'))
|
||||
{
|
||||
$error[] = $user->lang['WRONG_DATA_LANG'];
|
||||
}
|
||||
break;
|
||||
|
||||
// Relative path (appended $phpbb_root_path)
|
||||
case 'rpath':
|
||||
case 'rwpath':
|
||||
if (!$cfg_array[$config_name])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$destination = $cfg_array[$config_name];
|
||||
|
||||
// Adjust destination path (no trailing slash)
|
||||
if (substr($destination, -1, 1) == '/' || substr($destination, -1, 1) == '\\')
|
||||
{
|
||||
$destination = substr($destination, 0, -1);
|
||||
}
|
||||
|
||||
$destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination);
|
||||
if ($destination && ($destination[0] == '/' || $destination[0] == "\\"))
|
||||
{
|
||||
$destination = '';
|
||||
}
|
||||
|
||||
$cfg_array[$config_name] = trim($destination);
|
||||
|
||||
// Path being relative (still prefixed by phpbb_root_path), but with the ability to escape the root dir...
|
||||
case 'path':
|
||||
case 'wpath':
|
||||
|
||||
if (!$cfg_array[$config_name])
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
$cfg_array[$config_name] = trim($cfg_array[$config_name]);
|
||||
|
||||
// Make sure no NUL byte is present...
|
||||
if (strpos($cfg_array[$config_name], "\0") !== false || strpos($cfg_array[$config_name], '%00') !== false)
|
||||
{
|
||||
$cfg_array[$config_name] = '';
|
||||
break;
|
||||
}
|
||||
|
||||
$path = $phpbb_root_path . $cfg_array[$config_name];
|
||||
|
||||
if (!file_exists($path))
|
||||
{
|
||||
$error[] = sprintf($user->lang['DIRECTORY_DOES_NOT_EXIST'], $cfg_array[$config_name]);
|
||||
}
|
||||
|
||||
if (file_exists($path) && !is_dir($path))
|
||||
{
|
||||
$error[] = sprintf($user->lang['DIRECTORY_NOT_DIR'], $cfg_array[$config_name]);
|
||||
}
|
||||
|
||||
// Check if the path is writable
|
||||
if ($config_definition['validate'] == 'wpath' || $config_definition['validate'] == 'rwpath')
|
||||
{
|
||||
if (file_exists($path) && !$phpbb_filesystem->is_writable($path))
|
||||
{
|
||||
$error[] = sprintf($user->lang['DIRECTORY_NOT_WRITABLE'], $cfg_array[$config_name]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
/**
|
||||
* Validate a config value
|
||||
*
|
||||
* @event core.validate_config_variable
|
||||
* @var array cfg_array Array with config values
|
||||
* @var string config_name Name of the config we validate
|
||||
* @var array config_definition Array with the options for
|
||||
* this config
|
||||
* @var array error Array of errors, the errors should
|
||||
* be strings only, language keys are
|
||||
* not replaced afterwards
|
||||
* @since 3.1.0-a1
|
||||
*/
|
||||
$vars = array('cfg_array', 'config_name', 'config_definition', 'error');
|
||||
extract($phpbb_dispatcher->trigger_event('core.validate_config_variable', compact($vars)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whatever or not a variable is OK for use in the Database
|
||||
* param mixed $value_ary An array of the form array(array('lang' => ..., 'value' => ..., 'column_type' =>))'
|
||||
* param mixed $error The error array
|
||||
*/
|
||||
function validate_range($value_ary, &$error)
|
||||
{
|
||||
global $user;
|
||||
|
||||
$column_types = array(
|
||||
'BOOL' => array('php_type' => 'int', 'min' => 0, 'max' => 1),
|
||||
'USINT' => array('php_type' => 'int', 'min' => 0, 'max' => 65535),
|
||||
'UINT' => array('php_type' => 'int', 'min' => 0, 'max' => (int) 0x7fffffff),
|
||||
// Do not use (int) 0x80000000 - it evaluates to different
|
||||
// values on 32-bit and 64-bit systems.
|
||||
// Apparently -2147483648 is a float on 32-bit systems,
|
||||
// despite fitting in an int, thus explicit cast is needed.
|
||||
'INT' => array('php_type' => 'int', 'min' => (int) -2147483648, 'max' => (int) 0x7fffffff),
|
||||
'TINT' => array('php_type' => 'int', 'min' => -128, 'max' => 127),
|
||||
|
||||
'VCHAR' => array('php_type' => 'string', 'min' => 0, 'max' => 255),
|
||||
);
|
||||
foreach ($value_ary as $value)
|
||||
{
|
||||
$column = explode(':', $value['column_type']);
|
||||
if (!isset($column_types[$column[0]]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
$type = $column_types[$column[0]];
|
||||
}
|
||||
|
||||
switch ($type['php_type'])
|
||||
{
|
||||
case 'string' :
|
||||
$max = (isset($column[1])) ? min($column[1],$type['max']) : $type['max'];
|
||||
if (utf8_strlen($value['value']) > $max)
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_LONG'], $user->lang[$value['lang']], $max);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'int':
|
||||
$min = (isset($column[1])) ? max($column[1],$type['min']) : $type['min'];
|
||||
$max = (isset($column[2])) ? min($column[2],$type['max']) : $type['max'];
|
||||
if ($value['value'] < $min)
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_LOW'], $user->lang[$value['lang']], $min);
|
||||
}
|
||||
else if ($value['value'] > $max)
|
||||
{
|
||||
$error[] = sprintf($user->lang['SETTING_TOO_BIG'], $user->lang[$value['lang']], $max);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts new config display_vars into an exisiting display_vars array
|
||||
* at the given position.
|
||||
*
|
||||
* @param array $display_vars An array of existing config display vars
|
||||
* @param array $add_config_vars An array of new config display vars
|
||||
* @param array $where Where to place the new config vars,
|
||||
* before or after an exisiting config, as an array
|
||||
* of the form: array('after' => 'config_name') or
|
||||
* array('before' => 'config_name').
|
||||
* @return array The array of config display vars
|
||||
*/
|
||||
function phpbb_insert_config_array($display_vars, $add_config_vars, $where)
|
||||
{
|
||||
if (is_array($where) && array_key_exists(current($where), $display_vars))
|
||||
{
|
||||
$position = array_search(current($where), array_keys($display_vars)) + ((key($where) == 'before') ? 0 : 1);
|
||||
$display_vars = array_merge(
|
||||
array_slice($display_vars, 0, $position),
|
||||
$add_config_vars,
|
||||
array_slice($display_vars, $position)
|
||||
);
|
||||
}
|
||||
|
||||
return $display_vars;
|
||||
}
|
||||
3109
includes/functions_admin.php
Normal file
3109
includes/functions_admin.php
Normal file
File diff suppressed because it is too large
Load Diff
513
includes/functions_compatibility.php
Normal file
513
includes/functions_compatibility.php
Normal file
@@ -0,0 +1,513 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user avatar
|
||||
*
|
||||
* @deprecated 3.1.0-a1 (To be removed: 3.3.0)
|
||||
*
|
||||
* @param string $avatar Users assigned avatar name
|
||||
* @param int $avatar_type Type of avatar
|
||||
* @param string $avatar_width Width of users avatar
|
||||
* @param string $avatar_height Height of users avatar
|
||||
* @param string $alt Optional language string for alt tag within image, can be a language key or text
|
||||
* @param bool $ignore_config Ignores the config-setting, to be still able to view the avatar in the UCP
|
||||
* @param bool $lazy If true, will be lazy loaded (requires JS)
|
||||
*
|
||||
* @return string Avatar image
|
||||
*/
|
||||
function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR', $ignore_config = false, $lazy = false)
|
||||
{
|
||||
// map arguments to new function phpbb_get_avatar()
|
||||
$row = array(
|
||||
'avatar' => $avatar,
|
||||
'avatar_type' => $avatar_type,
|
||||
'avatar_width' => $avatar_width,
|
||||
'avatar_height' => $avatar_height,
|
||||
);
|
||||
|
||||
return phpbb_get_avatar($row, $alt, $ignore_config, $lazy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hash the password
|
||||
*
|
||||
* @deprecated 3.1.0-a2 (To be removed: 3.3.0)
|
||||
*
|
||||
* @param string $password Password to be hashed
|
||||
*
|
||||
* @return string|bool Password hash or false if something went wrong during hashing
|
||||
*/
|
||||
function phpbb_hash($password)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
/* @var $passwords_manager \phpbb\passwords\manager */
|
||||
$passwords_manager = $phpbb_container->get('passwords.manager');
|
||||
return $passwords_manager->hash($password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for correct password
|
||||
*
|
||||
* @deprecated 3.1.0-a2 (To be removed: 3.3.0)
|
||||
*
|
||||
* @param string $password The password in plain text
|
||||
* @param string $hash The stored password hash
|
||||
*
|
||||
* @return bool Returns true if the password is correct, false if not.
|
||||
*/
|
||||
function phpbb_check_hash($password, $hash)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
/* @var $passwords_manager \phpbb\passwords\manager */
|
||||
$passwords_manager = $phpbb_container->get('passwords.manager');
|
||||
return $passwords_manager->check($password, $hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Eliminates useless . and .. components from specified path.
|
||||
*
|
||||
* Deprecated, use filesystem class instead
|
||||
*
|
||||
* @param string $path Path to clean
|
||||
* @return string Cleaned path
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function phpbb_clean_path($path)
|
||||
{
|
||||
global $phpbb_path_helper, $phpbb_container;
|
||||
|
||||
if (!$phpbb_path_helper && $phpbb_container)
|
||||
{
|
||||
/* @var $phpbb_path_helper \phpbb\path_helper */
|
||||
$phpbb_path_helper = $phpbb_container->get('path_helper');
|
||||
}
|
||||
else if (!$phpbb_path_helper)
|
||||
{
|
||||
global $phpbb_root_path, $phpEx;
|
||||
|
||||
// The container is not yet loaded, use a new instance
|
||||
if (!class_exists('\phpbb\path_helper'))
|
||||
{
|
||||
require($phpbb_root_path . 'phpbb/path_helper.' . $phpEx);
|
||||
}
|
||||
|
||||
$request = new phpbb\request\request();
|
||||
$phpbb_path_helper = new phpbb\path_helper(
|
||||
new phpbb\symfony_request(
|
||||
$request
|
||||
),
|
||||
new phpbb\filesystem\filesystem(),
|
||||
$request,
|
||||
$phpbb_root_path,
|
||||
$phpEx
|
||||
);
|
||||
}
|
||||
|
||||
return $phpbb_path_helper->clean_path($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a timezone
|
||||
*
|
||||
* @param string $default A timezone to select
|
||||
* @param boolean $truncate Shall we truncate the options text
|
||||
*
|
||||
* @return string Returns the options for timezone selector only
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function tz_select($default = '', $truncate = false)
|
||||
{
|
||||
global $template, $user;
|
||||
|
||||
return phpbb_timezone_select($template, $user, $default, $truncate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache moderators. Called whenever permissions are changed
|
||||
* via admin_permissions. Changes of usernames and group names
|
||||
* must be carried through for the moderators table.
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
* @return null
|
||||
*/
|
||||
function cache_moderators()
|
||||
{
|
||||
global $db, $cache, $auth;
|
||||
return phpbb_cache_moderators($db, $cache, $auth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes moderators and administrators from foe lists.
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
* @param array|bool $group_id If an array, remove all members of this group from foe lists, or false to ignore
|
||||
* @param array|bool $user_id If an array, remove this user from foe lists, or false to ignore
|
||||
* @return null
|
||||
*/
|
||||
function update_foes($group_id = false, $user_id = false)
|
||||
{
|
||||
global $db, $auth;
|
||||
return phpbb_update_foes($db, $auth, $group_id, $user_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user rank title and image
|
||||
*
|
||||
* @param int $user_rank the current stored users rank id
|
||||
* @param int $user_posts the users number of posts
|
||||
* @param string &$rank_title the rank title will be stored here after execution
|
||||
* @param string &$rank_img the rank image as full img tag is stored here after execution
|
||||
* @param string &$rank_img_src the rank image source is stored here after execution
|
||||
*
|
||||
* @deprecated 3.1.0-RC5 (To be removed: 3.3.0)
|
||||
*
|
||||
* Note: since we do not want to break backwards-compatibility, this function will only properly assign ranks to guests if you call it for them with user_posts == false
|
||||
*/
|
||||
function get_user_rank($user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src)
|
||||
{
|
||||
global $phpbb_root_path, $phpEx;
|
||||
if (!function_exists('phpbb_get_user_rank'))
|
||||
{
|
||||
include($phpbb_root_path . 'includes/functions_display.' . $phpEx);
|
||||
}
|
||||
|
||||
$rank_data = phpbb_get_user_rank(array('user_rank' => $user_rank), $user_posts);
|
||||
$rank_title = $rank_data['title'];
|
||||
$rank_img = $rank_data['img'];
|
||||
$rank_img_src = $rank_data['img_src'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve contents from remotely stored file
|
||||
*
|
||||
* @deprecated 3.1.2 Use file_downloader instead
|
||||
*/
|
||||
function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 6)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
// Get file downloader and assign $errstr and $errno
|
||||
/* @var $file_downloader \phpbb\file_downloader */
|
||||
$file_downloader = $phpbb_container->get('file_downloader');
|
||||
|
||||
$file_data = $file_downloader->get($host, $directory, $filename, $port, $timeout);
|
||||
$errstr = $file_downloader->get_error_string();
|
||||
$errno = $file_downloader->get_error_number();
|
||||
|
||||
return $file_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add log entry
|
||||
*
|
||||
* @param string $mode The mode defines which log_type is used and from which log the entry is retrieved
|
||||
* @param int $forum_id Mode 'mod' ONLY: forum id of the related item, NOT INCLUDED otherwise
|
||||
* @param int $topic_id Mode 'mod' ONLY: topic id of the related item, NOT INCLUDED otherwise
|
||||
* @param int $reportee_id Mode 'user' ONLY: user id of the reportee, NOT INCLUDED otherwise
|
||||
* @param string $log_operation Name of the operation
|
||||
* @param array $additional_data More arguments can be added, depending on the log_type
|
||||
*
|
||||
* @return int|bool Returns the log_id, if the entry was added to the database, false otherwise.
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function add_log()
|
||||
{
|
||||
global $phpbb_log, $user;
|
||||
|
||||
$args = func_get_args();
|
||||
$mode = array_shift($args);
|
||||
|
||||
// This looks kind of dirty, but add_log has some additional data before the log_operation
|
||||
$additional_data = array();
|
||||
switch ($mode)
|
||||
{
|
||||
case 'admin':
|
||||
case 'critical':
|
||||
break;
|
||||
case 'mod':
|
||||
$additional_data['forum_id'] = array_shift($args);
|
||||
$additional_data['topic_id'] = array_shift($args);
|
||||
break;
|
||||
case 'user':
|
||||
$additional_data['reportee_id'] = array_shift($args);
|
||||
break;
|
||||
}
|
||||
|
||||
$log_operation = array_shift($args);
|
||||
$additional_data = array_merge($additional_data, $args);
|
||||
|
||||
$user_id = (empty($user->data)) ? ANONYMOUS : $user->data['user_id'];
|
||||
$user_ip = (empty($user->ip)) ? '' : $user->ip;
|
||||
|
||||
return $phpbb_log->add($mode, $user_id, $user_ip, $log_operation, time(), $additional_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a configuration option's value.
|
||||
*
|
||||
* Please note that this function does not update the is_dynamic value for
|
||||
* an already existing config option.
|
||||
*
|
||||
* @param string $config_name The configuration option's name
|
||||
* @param string $config_value New configuration value
|
||||
* @param bool $is_dynamic Whether this variable should be cached (false) or
|
||||
* if it changes too frequently (true) to be
|
||||
* efficiently cached.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function set_config($config_name, $config_value, $is_dynamic = false, \phpbb\config\config $set_config = null)
|
||||
{
|
||||
static $config = null;
|
||||
|
||||
if ($set_config !== null)
|
||||
{
|
||||
$config = $set_config;
|
||||
|
||||
if (empty($config_name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$config->set($config_name, $config_value, !$is_dynamic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments an integer config value directly in the database.
|
||||
*
|
||||
* @param string $config_name The configuration option's name
|
||||
* @param int $increment Amount to increment by
|
||||
* @param bool $is_dynamic Whether this variable should be cached (false) or
|
||||
* if it changes too frequently (true) to be
|
||||
* efficiently cached.
|
||||
*
|
||||
* @return null
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function set_config_count($config_name, $increment, $is_dynamic = false, \phpbb\config\config $set_config = null)
|
||||
{
|
||||
static $config = null;
|
||||
if ($set_config !== null)
|
||||
{
|
||||
$config = $set_config;
|
||||
if (empty($config_name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
$config->increment($config_name, $increment, !$is_dynamic);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function of \phpbb\request\request::variable which exists for backwards compatability.
|
||||
* See {@link \phpbb\request\request_interface::variable \phpbb\request\request_interface::variable} for
|
||||
* documentation of this function's use.
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
* @param mixed $var_name The form variable's name from which data shall be retrieved.
|
||||
* If the value is an array this may be an array of indizes which will give
|
||||
* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a")
|
||||
* then specifying array("var", 1) as the name will return "a".
|
||||
* If you pass an instance of {@link \phpbb\request\request_interface phpbb_request_interface}
|
||||
* as this parameter it will overwrite the current request class instance. If you do
|
||||
* not do so, it will create its own instance (but leave superglobals enabled).
|
||||
* @param mixed $default A default value that is returned if the variable was not set.
|
||||
* This function will always return a value of the same type as the default.
|
||||
* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters
|
||||
* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks
|
||||
* @param bool $cookie This param is mapped to \phpbb\request\request_interface::COOKIE as the last param for
|
||||
* \phpbb\request\request_interface::variable for backwards compatability reasons.
|
||||
* @param \phpbb\request\request_interface|null|false If an instance of \phpbb\request\request_interface is given the instance is stored in
|
||||
* a static variable and used for all further calls where this parameters is null. Until
|
||||
* the function is called with an instance it automatically creates a new \phpbb\request\request
|
||||
* instance on every call. By passing false this per-call instantiation can be restored
|
||||
* after having passed in a \phpbb\request\request_interface instance.
|
||||
*
|
||||
* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the
|
||||
* the same as that of $default. If the variable is not set $default is returned.
|
||||
*/
|
||||
function request_var($var_name, $default, $multibyte = false, $cookie = false, $request = null)
|
||||
{
|
||||
// This is all just an ugly hack to add "Dependency Injection" to a function
|
||||
// the only real code is the function call which maps this function to a method.
|
||||
static $static_request = null;
|
||||
if ($request instanceof \phpbb\request\request_interface)
|
||||
{
|
||||
$static_request = $request;
|
||||
if (empty($var_name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if ($request === false)
|
||||
{
|
||||
$static_request = null;
|
||||
if (empty($var_name))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
$tmp_request = $static_request;
|
||||
// no request class set, create a temporary one ourselves to keep backwards compatibility
|
||||
if ($tmp_request === null)
|
||||
{
|
||||
// false param: enable super globals, so the created request class does not
|
||||
// make super globals inaccessible everywhere outside this function.
|
||||
$tmp_request = new \phpbb\request\request(new \phpbb\request\type_cast_helper(), false);
|
||||
}
|
||||
return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? \phpbb\request\request_interface::COOKIE : \phpbb\request\request_interface::REQUEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tables of a database
|
||||
*
|
||||
* @deprecated 3.1.0 (To be removed: 3.3.0)
|
||||
*/
|
||||
function get_tables($db)
|
||||
{
|
||||
$db_tools_factory = new \phpbb\db\tools\factory();
|
||||
$db_tools = $db_tools_factory->get($db);
|
||||
|
||||
return $db_tools->sql_list_tables();
|
||||
}
|
||||
|
||||
/**
|
||||
* Global function for chmodding directories and files for internal use
|
||||
*
|
||||
* This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions.
|
||||
* The function determines owner and group from common.php file and sets the same to the provided file.
|
||||
* The function uses bit fields to build the permissions.
|
||||
* The function sets the appropiate execute bit on directories.
|
||||
*
|
||||
* Supported constants representing bit fields are:
|
||||
*
|
||||
* CHMOD_ALL - all permissions (7)
|
||||
* CHMOD_READ - read permission (4)
|
||||
* CHMOD_WRITE - write permission (2)
|
||||
* CHMOD_EXECUTE - execute permission (1)
|
||||
*
|
||||
* NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions.
|
||||
*
|
||||
* @param string $filename The file/directory to be chmodded
|
||||
* @param int $perms Permissions to set
|
||||
*
|
||||
* @return bool true on success, otherwise false
|
||||
*
|
||||
* @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::phpbb_chmod() instead
|
||||
*/
|
||||
function phpbb_chmod($filename, $perms = CHMOD_READ)
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
try
|
||||
{
|
||||
$phpbb_filesystem->phpbb_chmod($filename, $perms);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a file/directory is writable
|
||||
*
|
||||
* This function calls the native is_writable() when not running under
|
||||
* Windows and it is not disabled.
|
||||
*
|
||||
* @param string $file Path to perform write test on
|
||||
* @return bool True when the path is writable, otherwise false.
|
||||
*
|
||||
* @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_writable() instead
|
||||
*/
|
||||
function phpbb_is_writable($file)
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
return $phpbb_filesystem->is_writable($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a path ($path) is absolute or relative
|
||||
*
|
||||
* @param string $path Path to check absoluteness of
|
||||
* @return boolean
|
||||
*
|
||||
* @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::is_absolute_path() instead
|
||||
*/
|
||||
function phpbb_is_absolute($path)
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
return $phpbb_filesystem->is_absolute_path($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper for realpath
|
||||
*
|
||||
* @deprecated 3.2.0-dev use \phpbb\filesystem\filesystem::realpath() instead
|
||||
*/
|
||||
function phpbb_realpath($path)
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
return $phpbb_filesystem->realpath($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine which plural form we should use.
|
||||
* For some languages this is not as simple as for English.
|
||||
*
|
||||
* @param $rule int ID of the plural rule we want to use, see https://area51.phpbb.com/docs/dev/32x/language/plurals.html
|
||||
* @param $number int|float The number we want to get the plural case for. Float numbers are floored.
|
||||
* @return int The plural-case we need to use for the number plural-rule combination
|
||||
*
|
||||
* @deprecated 3.2.0-dev (To be removed: 3.3.0)
|
||||
*/
|
||||
function phpbb_get_plural_form($rule, $number)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
/** @var \phpbb\language\language $language */
|
||||
$language = $phpbb_container->get('language');
|
||||
return $language->get_plural_form($number, $rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool Always true
|
||||
* @deprecated 3.2.0-dev
|
||||
*/
|
||||
function phpbb_pcre_utf8_support()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
830
includes/functions_compress.php
Normal file
830
includes/functions_compress.php
Normal file
@@ -0,0 +1,830 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for handling archives (compression/decompression)
|
||||
*/
|
||||
class compress
|
||||
{
|
||||
var $fp = 0;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $filelist = array();
|
||||
|
||||
/**
|
||||
* Add file to archive
|
||||
*/
|
||||
function add_file($src, $src_rm_prefix = '', $src_add_prefix = '', $skip_files = '')
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$skip_files = explode(',', $skip_files);
|
||||
|
||||
// Remove rm prefix from src path
|
||||
$src_path = ($src_rm_prefix) ? preg_replace('#^(' . preg_quote($src_rm_prefix, '#') . ')#', '', $src) : $src;
|
||||
// Add src prefix
|
||||
$src_path = ($src_add_prefix) ? ($src_add_prefix . ((substr($src_add_prefix, -1) != '/') ? '/' : '') . $src_path) : $src_path;
|
||||
// Remove initial "/" if present
|
||||
$src_path = (substr($src_path, 0, 1) == '/') ? substr($src_path, 1) : $src_path;
|
||||
|
||||
if (is_file($phpbb_root_path . $src))
|
||||
{
|
||||
$this->data($src_path, file_get_contents("$phpbb_root_path$src"), stat("$phpbb_root_path$src"), false);
|
||||
}
|
||||
else if (is_dir($phpbb_root_path . $src))
|
||||
{
|
||||
// Clean up path, add closing / if not present
|
||||
$src_path = ($src_path && substr($src_path, -1) != '/') ? $src_path . '/' : $src_path;
|
||||
|
||||
$filelist = filelist("$phpbb_root_path$src", '', '*');
|
||||
krsort($filelist);
|
||||
|
||||
/**
|
||||
* Commented out, as adding the folders produces corrupted archives
|
||||
if ($src_path)
|
||||
{
|
||||
$this->data($src_path, '', true, stat("$phpbb_root_path$src"));
|
||||
}
|
||||
*/
|
||||
|
||||
foreach ($filelist as $path => $file_ary)
|
||||
{
|
||||
/**
|
||||
* Commented out, as adding the folders produces corrupted archives
|
||||
if ($path)
|
||||
{
|
||||
// Same as for src_path
|
||||
$path = (substr($path, 0, 1) == '/') ? substr($path, 1) : $path;
|
||||
$path = ($path && substr($path, -1) != '/') ? $path . '/' : $path;
|
||||
|
||||
$this->data("$src_path$path", '', true, stat("$phpbb_root_path$src$path"));
|
||||
}
|
||||
*/
|
||||
|
||||
foreach ($file_ary as $file)
|
||||
{
|
||||
if (in_array($path . $file, $skip_files))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->data("$src_path$path$file", file_get_contents("$phpbb_root_path$src$path$file"), stat("$phpbb_root_path$src$path$file"), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// $src does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom file (the filepath will not be adjusted)
|
||||
*/
|
||||
function add_custom_file($src, $filename)
|
||||
{
|
||||
if (!file_exists($src))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->data($filename, file_get_contents($src), stat($src), false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add file data
|
||||
*/
|
||||
function add_data($src, $name)
|
||||
{
|
||||
$stat = array();
|
||||
$stat[2] = 436; //384
|
||||
$stat[4] = $stat[5] = 0;
|
||||
$stat[7] = strlen($src);
|
||||
$stat[9] = time();
|
||||
$this->data($name, $src, $stat, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a file by that name as already been added and, if it has,
|
||||
* returns a new, unique name.
|
||||
*
|
||||
* @param string $name The filename
|
||||
* @return string A unique filename
|
||||
*/
|
||||
protected function unique_filename($name)
|
||||
{
|
||||
if (isset($this->filelist[$name]))
|
||||
{
|
||||
$start = $name;
|
||||
$ext = '';
|
||||
$this->filelist[$name]++;
|
||||
|
||||
// Separate the extension off the end of the filename to preserve it
|
||||
$pos = strrpos($name, '.');
|
||||
if ($pos !== false)
|
||||
{
|
||||
$start = substr($name, 0, $pos);
|
||||
$ext = substr($name, $pos);
|
||||
}
|
||||
|
||||
return $start . '_' . $this->filelist[$name] . $ext;
|
||||
}
|
||||
|
||||
$this->filelist[$name] = 0;
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return available methods
|
||||
*
|
||||
* @return array Array of strings of available compression methods (.tar, .tar.gz, .zip, etc.)
|
||||
*/
|
||||
static public function methods()
|
||||
{
|
||||
$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;
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux,
|
||||
* Marc Delisle, http://www.phpmyadmin.net/
|
||||
*
|
||||
* Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com
|
||||
*
|
||||
* Modified extensively by psoTFX and DavidMJ, (c) phpBB Limited, 2003
|
||||
*
|
||||
* Based on work by Eric Mueller and Denis125
|
||||
* Official ZIP file format: http://www.pkware.com/appnote.txt
|
||||
*/
|
||||
class compress_zip extends compress
|
||||
{
|
||||
var $datasec = array();
|
||||
var $ctrl_dir = array();
|
||||
var $eof_cdh = "\x50\x4b\x05\x06\x00\x00\x00\x00";
|
||||
|
||||
var $old_offset = 0;
|
||||
var $datasec_len = 0;
|
||||
|
||||
/**
|
||||
* @var \phpbb\filesystem\filesystem_interface
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct($mode, $file)
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
$this->fp = @fopen($file, $mode . 'b');
|
||||
$this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem();
|
||||
|
||||
if (!$this->fp)
|
||||
{
|
||||
trigger_error('Unable to open file ' . $file . ' [' . $mode . 'b]');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert unix to dos time
|
||||
*/
|
||||
function unix_to_dos_time($time)
|
||||
{
|
||||
$timearray = (!$time) ? getdate() : getdate($time);
|
||||
|
||||
if ($timearray['year'] < 1980)
|
||||
{
|
||||
$timearray['year'] = 1980;
|
||||
$timearray['mon'] = $timearray['mday'] = 1;
|
||||
$timearray['hours'] = $timearray['minutes'] = $timearray['seconds'] = 0;
|
||||
}
|
||||
|
||||
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract archive
|
||||
*/
|
||||
function extract($dst)
|
||||
{
|
||||
// Loop the file, looking for files and folders
|
||||
$dd_try = false;
|
||||
rewind($this->fp);
|
||||
|
||||
while (!feof($this->fp))
|
||||
{
|
||||
// Check if the signature is valid...
|
||||
$signature = fread($this->fp, 4);
|
||||
|
||||
switch ($signature)
|
||||
{
|
||||
// 'Local File Header'
|
||||
case "\x50\x4b\x03\x04":
|
||||
// Lets get everything we need.
|
||||
// We don't store the version needed to extract, the general purpose bit flag or the date and time fields
|
||||
$data = unpack("@4/vc_method/@10/Vcrc/Vc_size/Vuc_size/vname_len/vextra_field", fread($this->fp, 26));
|
||||
$file_name = fread($this->fp, $data['name_len']); // filename
|
||||
|
||||
if ($data['extra_field'])
|
||||
{
|
||||
fread($this->fp, $data['extra_field']); // extra field
|
||||
}
|
||||
|
||||
$target_filename = "$dst$file_name";
|
||||
|
||||
if (!$data['uc_size'] && !$data['crc'] && substr($file_name, -1, 1) == '/')
|
||||
{
|
||||
if (!is_dir($target_filename))
|
||||
{
|
||||
$str = '';
|
||||
$folders = explode('/', $target_filename);
|
||||
|
||||
// Create and folders and subfolders if they do not exist
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
$folder = trim($folder);
|
||||
if (!$folder)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$str = (!empty($str)) ? $str . '/' . $folder : $folder;
|
||||
if (!is_dir($str))
|
||||
{
|
||||
if (!@mkdir($str, 0777))
|
||||
{
|
||||
trigger_error("Could not create directory $folder");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// This is a directory, we are not writting files
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some archivers are punks, they don't include folders in their archives!
|
||||
$str = '';
|
||||
$folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME));
|
||||
|
||||
// Create and folders and subfolders if they do not exist
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
$folder = trim($folder);
|
||||
if (!$folder)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$str = (!empty($str)) ? $str . '/' . $folder : $folder;
|
||||
if (!is_dir($str))
|
||||
{
|
||||
if (!@mkdir($str, 0777))
|
||||
{
|
||||
trigger_error("Could not create directory $folder");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$data['uc_size'])
|
||||
{
|
||||
$content = '';
|
||||
}
|
||||
else
|
||||
{
|
||||
$content = fread($this->fp, $data['c_size']);
|
||||
}
|
||||
|
||||
$fp = fopen($target_filename, "w");
|
||||
|
||||
switch ($data['c_method'])
|
||||
{
|
||||
case 0:
|
||||
// Not compressed
|
||||
fwrite($fp, $content);
|
||||
break;
|
||||
|
||||
case 8:
|
||||
// Deflate
|
||||
fwrite($fp, gzinflate($content, $data['uc_size']));
|
||||
break;
|
||||
|
||||
case 12:
|
||||
// Bzip2
|
||||
fwrite($fp, bzdecompress($content));
|
||||
break;
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
break;
|
||||
|
||||
// We hit the 'Central Directory Header', we can stop because nothing else in here requires our attention
|
||||
// or we hit the end of the central directory record, we can safely end the loop as we are totally finished with looking for files and folders
|
||||
case "\x50\x4b\x01\x02":
|
||||
// This case should simply never happen.. but it does exist..
|
||||
case "\x50\x4b\x05\x06":
|
||||
break 2;
|
||||
|
||||
// 'Packed to Removable Disk', ignore it and look for the next signature...
|
||||
case 'PK00':
|
||||
continue 2;
|
||||
|
||||
// We have encountered a header that is weird. Lets look for better data...
|
||||
default:
|
||||
if (!$dd_try)
|
||||
{
|
||||
// Unexpected header. Trying to detect wrong placed 'Data Descriptor';
|
||||
$dd_try = true;
|
||||
fseek($this->fp, 8, SEEK_CUR); // Jump over 'crc-32'(4) 'compressed-size'(4), 'uncompressed-size'(4)
|
||||
continue 2;
|
||||
}
|
||||
trigger_error("Unexpected header, ending loop");
|
||||
break 2;
|
||||
}
|
||||
|
||||
$dd_try = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close archive
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
// Write out central file directory and footer ... if it exists
|
||||
if (count($this->ctrl_dir))
|
||||
{
|
||||
fwrite($this->fp, $this->file());
|
||||
}
|
||||
fclose($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the structures ... note we assume version made by is MSDOS
|
||||
*/
|
||||
function data($name, $data, $stat, $is_dir = false)
|
||||
{
|
||||
$name = str_replace('\\', '/', $name);
|
||||
$name = $this->unique_filename($name);
|
||||
|
||||
$hexdtime = pack('V', $this->unix_to_dos_time($stat[9]));
|
||||
|
||||
if ($is_dir)
|
||||
{
|
||||
$unc_len = $c_len = $crc = 0;
|
||||
$zdata = '';
|
||||
$var_ext = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
$unc_len = strlen($data);
|
||||
$crc = crc32($data);
|
||||
$zdata = gzdeflate($data);
|
||||
$c_len = strlen($zdata);
|
||||
$var_ext = 20;
|
||||
|
||||
// Did we compress? No, then use data as is
|
||||
if ($c_len >= $unc_len)
|
||||
{
|
||||
$zdata = $data;
|
||||
$c_len = $unc_len;
|
||||
$var_ext = 10;
|
||||
}
|
||||
}
|
||||
unset($data);
|
||||
|
||||
// If we didn't compress set method to store, else deflate
|
||||
$c_method = ($c_len == $unc_len) ? "\x00\x00" : "\x08\x00";
|
||||
|
||||
// Are we a file or a directory? Set archive for file
|
||||
$attrib = ($is_dir) ? 16 : 32;
|
||||
|
||||
// File Record Header
|
||||
$fr = "\x50\x4b\x03\x04"; // Local file header 4bytes
|
||||
$fr .= pack('v', $var_ext); // ver needed to extract 2bytes
|
||||
$fr .= "\x00\x00"; // gen purpose bit flag 2bytes
|
||||
$fr .= $c_method; // compression method 2bytes
|
||||
$fr .= $hexdtime; // last mod time and date 2+2bytes
|
||||
$fr .= pack('V', $crc); // crc32 4bytes
|
||||
$fr .= pack('V', $c_len); // compressed filesize 4bytes
|
||||
$fr .= pack('V', $unc_len); // uncompressed filesize 4bytes
|
||||
$fr .= pack('v', strlen($name));// length of filename 2bytes
|
||||
|
||||
$fr .= pack('v', 0); // extra field length 2bytes
|
||||
$fr .= $name;
|
||||
$fr .= $zdata;
|
||||
unset($zdata);
|
||||
|
||||
$this->datasec_len += strlen($fr);
|
||||
|
||||
// Add data to file ... by writing data out incrementally we save some memory
|
||||
fwrite($this->fp, $fr);
|
||||
unset($fr);
|
||||
|
||||
// Central Directory Header
|
||||
$cdrec = "\x50\x4b\x01\x02"; // header 4bytes
|
||||
$cdrec .= "\x00\x00"; // version made by
|
||||
$cdrec .= pack('v', $var_ext); // version needed to extract
|
||||
$cdrec .= "\x00\x00"; // gen purpose bit flag
|
||||
$cdrec .= $c_method; // compression method
|
||||
$cdrec .= $hexdtime; // last mod time & date
|
||||
$cdrec .= pack('V', $crc); // crc32
|
||||
$cdrec .= pack('V', $c_len); // compressed filesize
|
||||
$cdrec .= pack('V', $unc_len); // uncompressed filesize
|
||||
$cdrec .= pack('v', strlen($name)); // length of filename
|
||||
$cdrec .= pack('v', 0); // extra field length
|
||||
$cdrec .= pack('v', 0); // file comment length
|
||||
$cdrec .= pack('v', 0); // disk number start
|
||||
$cdrec .= pack('v', 0); // internal file attributes
|
||||
$cdrec .= pack('V', $attrib); // external file attributes
|
||||
$cdrec .= pack('V', $this->old_offset); // relative offset of local header
|
||||
$cdrec .= $name;
|
||||
|
||||
// Save to central directory
|
||||
$this->ctrl_dir[] = $cdrec;
|
||||
|
||||
$this->old_offset = $this->datasec_len;
|
||||
}
|
||||
|
||||
/**
|
||||
* file
|
||||
*/
|
||||
function file()
|
||||
{
|
||||
$ctrldir = implode('', $this->ctrl_dir);
|
||||
|
||||
return $ctrldir . $this->eof_cdh .
|
||||
pack('v', count($this->ctrl_dir)) . // total # of entries "on this disk"
|
||||
pack('v', count($this->ctrl_dir)) . // total # of entries overall
|
||||
pack('V', strlen($ctrldir)) . // size of central dir
|
||||
pack('V', $this->datasec_len) . // offset to start of central dir
|
||||
"\x00\x00"; // .zip file comment length
|
||||
}
|
||||
|
||||
/**
|
||||
* Download archive
|
||||
*/
|
||||
function download($filename, $download_name = false)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
if ($download_name === false)
|
||||
{
|
||||
$download_name = $filename;
|
||||
}
|
||||
|
||||
$mimetype = 'application/zip';
|
||||
|
||||
header('Cache-Control: private, no-cache');
|
||||
header("Content-Type: $mimetype; name=\"$download_name.zip\"");
|
||||
header("Content-disposition: attachment; filename=$download_name.zip");
|
||||
|
||||
$fp = @fopen("{$phpbb_root_path}store/$filename.zip", 'rb');
|
||||
if ($fp)
|
||||
{
|
||||
while ($buffer = fread($fp, 1024))
|
||||
{
|
||||
echo $buffer;
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tar/tar.gz compression routine
|
||||
* Header/checksum creation derived from tarfile.pl, (c) Tom Horsley, 1994
|
||||
*/
|
||||
class compress_tar extends compress
|
||||
{
|
||||
var $isgz = false;
|
||||
var $isbz = false;
|
||||
var $filename = '';
|
||||
var $mode = '';
|
||||
var $type = '';
|
||||
var $wrote = false;
|
||||
|
||||
/**
|
||||
* @var \phpbb\filesystem\filesystem_interface
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
function __construct($mode, $file, $type = '')
|
||||
{
|
||||
global $phpbb_filesystem;
|
||||
|
||||
$type = (!$type) ? $file : $type;
|
||||
$this->isgz = preg_match('#(\.tar\.gz|\.tgz)$#', $type);
|
||||
$this->isbz = preg_match('#\.tar\.bz2$#', $type);
|
||||
|
||||
$this->mode = &$mode;
|
||||
$this->file = &$file;
|
||||
$this->type = &$type;
|
||||
$this->open();
|
||||
|
||||
$this->filesystem = ($phpbb_filesystem instanceof \phpbb\filesystem\filesystem_interface) ? $phpbb_filesystem : new \phpbb\filesystem\filesystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract archive
|
||||
*/
|
||||
function extract($dst)
|
||||
{
|
||||
$fzread = ($this->isbz && function_exists('bzread')) ? 'bzread' : (($this->isgz && @extension_loaded('zlib')) ? 'gzread' : 'fread');
|
||||
|
||||
// Run through the file and grab directory entries
|
||||
while ($buffer = $fzread($this->fp, 512))
|
||||
{
|
||||
$tmp = unpack('A6magic', substr($buffer, 257, 6));
|
||||
|
||||
if (trim($tmp['magic']) == 'ustar')
|
||||
{
|
||||
$tmp = unpack('A100name', $buffer);
|
||||
$filename = trim($tmp['name']);
|
||||
|
||||
$tmp = unpack('Atype', substr($buffer, 156, 1));
|
||||
$filetype = (int) trim($tmp['type']);
|
||||
|
||||
$tmp = unpack('A12size', substr($buffer, 124, 12));
|
||||
$filesize = octdec((int) trim($tmp['size']));
|
||||
|
||||
$target_filename = "$dst$filename";
|
||||
|
||||
if ($filetype == 5)
|
||||
{
|
||||
if (!is_dir($target_filename))
|
||||
{
|
||||
$str = '';
|
||||
$folders = explode('/', $target_filename);
|
||||
|
||||
// Create and folders and subfolders if they do not exist
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
$folder = trim($folder);
|
||||
if (!$folder)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$str = (!empty($str)) ? $str . '/' . $folder : $folder;
|
||||
if (!is_dir($str))
|
||||
{
|
||||
if (!@mkdir($str, 0777))
|
||||
{
|
||||
trigger_error("Could not create directory $folder");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ($filesize >= 0 && ($filetype == 0 || $filetype == "\0"))
|
||||
{
|
||||
// Some archivers are punks, they don't properly order the folders in their archives!
|
||||
$str = '';
|
||||
$folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME));
|
||||
|
||||
// Create and folders and subfolders if they do not exist
|
||||
foreach ($folders as $folder)
|
||||
{
|
||||
$folder = trim($folder);
|
||||
if (!$folder)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$str = (!empty($str)) ? $str . '/' . $folder : $folder;
|
||||
if (!is_dir($str))
|
||||
{
|
||||
if (!@mkdir($str, 0777))
|
||||
{
|
||||
trigger_error("Could not create directory $folder");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->filesystem->phpbb_chmod($str, CHMOD_READ | CHMOD_WRITE);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write out the files
|
||||
if (!($fp = fopen($target_filename, 'wb')))
|
||||
{
|
||||
trigger_error("Couldn't create file $filename");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$this->filesystem->phpbb_chmod($target_filename, CHMOD_READ);
|
||||
}
|
||||
catch (\phpbb\filesystem\exception\filesystem_exception $e)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// Grab the file contents
|
||||
fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize);
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close archive
|
||||
*/
|
||||
function close()
|
||||
{
|
||||
$fzclose = ($this->isbz && function_exists('bzclose')) ? 'bzclose' : (($this->isgz && @extension_loaded('zlib')) ? 'gzclose' : 'fclose');
|
||||
|
||||
if ($this->wrote)
|
||||
{
|
||||
$fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');
|
||||
|
||||
// The end of a tar archive ends in two records of all NULLs (1024 bytes of \0)
|
||||
$fzwrite($this->fp, str_repeat("\0", 1024));
|
||||
}
|
||||
|
||||
$fzclose($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the structures
|
||||
*/
|
||||
function data($name, $data, $stat, $is_dir = false)
|
||||
{
|
||||
$name = $this->unique_filename($name);
|
||||
$this->wrote = true;
|
||||
$fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite');
|
||||
|
||||
$typeflag = ($is_dir) ? '5' : '';
|
||||
|
||||
// This is the header data, it contains all the info we know about the file or folder that we are about to archive
|
||||
$header = '';
|
||||
$header .= pack('a100', $name); // file name
|
||||
$header .= pack('a8', sprintf("%07o", $stat[2])); // file mode
|
||||
$header .= pack('a8', sprintf("%07o", $stat[4])); // owner id
|
||||
$header .= pack('a8', sprintf("%07o", $stat[5])); // group id
|
||||
$header .= pack('a12', sprintf("%011o", $stat[7])); // file size
|
||||
$header .= pack('a12', sprintf("%011o", $stat[9])); // last mod time
|
||||
|
||||
// Checksum
|
||||
$checksum = 0;
|
||||
for ($i = 0; $i < 148; $i++)
|
||||
{
|
||||
$checksum += ord($header[$i]);
|
||||
}
|
||||
|
||||
// We precompute the rest of the hash, this saves us time in the loop and allows us to insert our hash without resorting to string functions
|
||||
$checksum += 2415 + (($is_dir) ? 53 : 0);
|
||||
|
||||
$header .= pack('a8', sprintf("%07o", $checksum)); // checksum
|
||||
$header .= pack('a1', $typeflag); // link indicator
|
||||
$header .= pack('a100', ''); // name of linked file
|
||||
$header .= pack('a6', 'ustar'); // ustar indicator
|
||||
$header .= pack('a2', '00'); // ustar version
|
||||
$header .= pack('a32', 'Unknown'); // owner name
|
||||
$header .= pack('a32', 'Unknown'); // group name
|
||||
$header .= pack('a8', ''); // device major number
|
||||
$header .= pack('a8', ''); // device minor number
|
||||
$header .= pack('a155', ''); // filename prefix
|
||||
$header .= pack('a12', ''); // end
|
||||
|
||||
// This writes the entire file in one shot. Header, followed by data and then null padded to a multiple of 512
|
||||
$fzwrite($this->fp, $header . (($stat[7] !== 0 && !$is_dir) ? $data . str_repeat("\0", (($stat[7] + 511) &~ 511) - $stat[7]) : ''));
|
||||
unset($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open archive
|
||||
*/
|
||||
function open()
|
||||
{
|
||||
$fzopen = ($this->isbz && function_exists('bzopen')) ? 'bzopen' : (($this->isgz && @extension_loaded('zlib')) ? 'gzopen' : 'fopen');
|
||||
$this->fp = @$fzopen($this->file, $this->mode . (($fzopen == 'bzopen') ? '' : 'b') . (($fzopen == 'gzopen') ? '9' : ''));
|
||||
|
||||
if (!$this->fp)
|
||||
{
|
||||
trigger_error('Unable to open file ' . $this->file . ' [' . $fzopen . ' - ' . $this->mode . 'b]');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download archive
|
||||
*/
|
||||
function download($filename, $download_name = false)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
if ($download_name === false)
|
||||
{
|
||||
$download_name = $filename;
|
||||
}
|
||||
|
||||
switch ($this->type)
|
||||
{
|
||||
case '.tar':
|
||||
$mimetype = 'application/x-tar';
|
||||
break;
|
||||
|
||||
case '.tar.gz':
|
||||
$mimetype = 'application/x-gzip';
|
||||
break;
|
||||
|
||||
case '.tar.bz2':
|
||||
$mimetype = 'application/x-bzip2';
|
||||
break;
|
||||
|
||||
default:
|
||||
$mimetype = 'application/octet-stream';
|
||||
break;
|
||||
}
|
||||
|
||||
header('Cache-Control: private, no-cache');
|
||||
header("Content-Type: $mimetype; name=\"$download_name$this->type\"");
|
||||
header("Content-disposition: attachment; filename=$download_name$this->type");
|
||||
|
||||
$fp = @fopen("{$phpbb_root_path}store/$filename$this->type", 'rb');
|
||||
if ($fp)
|
||||
{
|
||||
while ($buffer = fread($fp, 1024))
|
||||
{
|
||||
echo $buffer;
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
1805
includes/functions_content.php
Normal file
1805
includes/functions_content.php
Normal file
File diff suppressed because it is too large
Load Diff
2514
includes/functions_convert.php
Normal file
2514
includes/functions_convert.php
Normal file
File diff suppressed because it is too large
Load Diff
210
includes/functions_database_helper.php
Normal file
210
includes/functions_database_helper.php
Normal file
@@ -0,0 +1,210 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates rows in given table from a set of values to a new value.
|
||||
* If this results in rows violating uniqueness constraints, the duplicate
|
||||
* rows are eliminated.
|
||||
*
|
||||
* The only supported table is bookmarks.
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db Database object
|
||||
* @param string $table Table on which to perform the update
|
||||
* @param string $column Column whose values to change
|
||||
* @param array $from_values An array of values that should be changed
|
||||
* @param int $to_value The new value
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_update_rows_avoiding_duplicates(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value)
|
||||
{
|
||||
$sql = "SELECT $column, user_id
|
||||
FROM $table
|
||||
WHERE " . $db->sql_in_set($column, $from_values);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$old_user_ids = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$old_user_ids[$row[$column]][] = (int) $row['user_id'];
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = "SELECT $column, user_id
|
||||
FROM $table
|
||||
WHERE $column = " . (int) $to_value;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$new_user_ids = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$new_user_ids[$row[$column]][] = (int) $row['user_id'];
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$queries = array();
|
||||
foreach ($from_values as $from_value)
|
||||
{
|
||||
if (!isset($old_user_ids[$from_value]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (empty($new_user_ids))
|
||||
{
|
||||
$sql = "UPDATE $table
|
||||
SET $column = " . (int) $to_value . "
|
||||
WHERE $column = '" . $db->sql_escape($from_value) . "'";
|
||||
$queries[] = $sql;
|
||||
}
|
||||
else
|
||||
{
|
||||
$different_user_ids = array_diff($old_user_ids[$from_value], $new_user_ids[$to_value]);
|
||||
if (!empty($different_user_ids))
|
||||
{
|
||||
$sql = "UPDATE $table
|
||||
SET $column = " . (int) $to_value . "
|
||||
WHERE $column = '" . $db->sql_escape($from_value) . "'
|
||||
AND " . $db->sql_in_set('user_id', $different_user_ids);
|
||||
$queries[] = $sql;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($queries))
|
||||
{
|
||||
$db->sql_transaction('begin');
|
||||
|
||||
foreach ($queries as $sql)
|
||||
{
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM $table
|
||||
WHERE " . $db->sql_in_set($column, $from_values);
|
||||
$db->sql_query($sql);
|
||||
|
||||
$db->sql_transaction('commit');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates rows in given table from a set of values to a new value.
|
||||
* If this results in rows violating uniqueness constraints, the duplicate
|
||||
* rows are merged respecting notify_status (0 takes precedence over 1).
|
||||
*
|
||||
* The only supported table is topics_watch.
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db Database object
|
||||
* @param string $table Table on which to perform the update
|
||||
* @param string $column Column whose values to change
|
||||
* @param array $from_values An array of values that should be changed
|
||||
* @param int $to_value The new value
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_update_rows_avoiding_duplicates_notify_status(\phpbb\db\driver\driver_interface $db, $table, $column, $from_values, $to_value)
|
||||
{
|
||||
$sql = "SELECT $column, user_id, notify_status
|
||||
FROM $table
|
||||
WHERE " . $db->sql_in_set($column, $from_values);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$old_user_ids = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$old_user_ids[(int) $row['notify_status']][$row[$column]][] = (int) $row['user_id'];
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$sql = "SELECT $column, user_id
|
||||
FROM $table
|
||||
WHERE $column = " . (int) $to_value;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$new_user_ids = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$new_user_ids[$row[$column]][] = (int) $row['user_id'];
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$queries = array();
|
||||
$extra_updates = array(
|
||||
0 => 'notify_status = 0',
|
||||
1 => '',
|
||||
);
|
||||
foreach ($from_values as $from_value)
|
||||
{
|
||||
foreach ($extra_updates as $notify_status => $extra_update)
|
||||
{
|
||||
if (!isset($old_user_ids[$notify_status][$from_value]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (empty($new_user_ids))
|
||||
{
|
||||
$sql = "UPDATE $table
|
||||
SET $column = " . (int) $to_value . "
|
||||
WHERE $column = '" . $db->sql_escape($from_value) . "'";
|
||||
$queries[] = $sql;
|
||||
}
|
||||
else
|
||||
{
|
||||
$different_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $new_user_ids[$to_value]);
|
||||
if (!empty($different_user_ids))
|
||||
{
|
||||
$sql = "UPDATE $table
|
||||
SET $column = " . (int) $to_value . "
|
||||
WHERE $column = '" . $db->sql_escape($from_value) . "'
|
||||
AND " . $db->sql_in_set('user_id', $different_user_ids);
|
||||
$queries[] = $sql;
|
||||
}
|
||||
|
||||
if ($extra_update)
|
||||
{
|
||||
$same_user_ids = array_diff($old_user_ids[$notify_status][$from_value], $different_user_ids);
|
||||
if (!empty($same_user_ids))
|
||||
{
|
||||
$sql = "UPDATE $table
|
||||
SET $extra_update
|
||||
WHERE $column = '" . (int) $to_value . "'
|
||||
AND " . $db->sql_in_set('user_id', $same_user_ids);
|
||||
$queries[] = $sql;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($queries))
|
||||
{
|
||||
$db->sql_transaction('begin');
|
||||
|
||||
foreach ($queries as $sql)
|
||||
{
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
$sql = "DELETE FROM $table
|
||||
WHERE " . $db->sql_in_set($column, $from_values);
|
||||
$db->sql_query($sql);
|
||||
|
||||
$db->sql_transaction('commit');
|
||||
}
|
||||
}
|
||||
1733
includes/functions_display.php
Normal file
1733
includes/functions_display.php
Normal file
File diff suppressed because it is too large
Load Diff
790
includes/functions_download.php
Normal file
790
includes/functions_download.php
Normal file
@@ -0,0 +1,790 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* A simplified function to deliver avatars
|
||||
* The argument needs to be checked before calling this function.
|
||||
*/
|
||||
function send_avatar_to_browser($file, $browser)
|
||||
{
|
||||
global $config, $phpbb_root_path;
|
||||
|
||||
$prefix = $config['avatar_salt'] . '_';
|
||||
$image_dir = $config['avatar_path'];
|
||||
|
||||
// Adjust image_dir path (no trailing slash)
|
||||
if (substr($image_dir, -1, 1) == '/' || substr($image_dir, -1, 1) == '\\')
|
||||
{
|
||||
$image_dir = substr($image_dir, 0, -1) . '/';
|
||||
}
|
||||
$image_dir = str_replace(array('../', '..\\', './', '.\\'), '', $image_dir);
|
||||
|
||||
if ($image_dir && ($image_dir[0] == '/' || $image_dir[0] == '\\'))
|
||||
{
|
||||
$image_dir = '';
|
||||
}
|
||||
$file_path = $phpbb_root_path . $image_dir . '/' . $prefix . $file;
|
||||
|
||||
if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent())
|
||||
{
|
||||
header('Cache-Control: public');
|
||||
|
||||
$image_data = @getimagesize($file_path);
|
||||
header('Content-Type: ' . image_type_to_mime_type($image_data[2]));
|
||||
|
||||
if ((strpos(strtolower($browser), 'msie') !== false) && !phpbb_is_greater_ie_version($browser, 7))
|
||||
{
|
||||
header('Content-Disposition: attachment; ' . header_filename($file));
|
||||
|
||||
if (strpos(strtolower($browser), 'msie 6.0') !== false)
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Content-Disposition: inline; ' . header_filename($file));
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
}
|
||||
|
||||
$size = @filesize($file_path);
|
||||
if ($size)
|
||||
{
|
||||
header("Content-Length: $size");
|
||||
}
|
||||
|
||||
if (@readfile($file_path) == false)
|
||||
{
|
||||
$fp = @fopen($file_path, 'rb');
|
||||
|
||||
if ($fp !== false)
|
||||
{
|
||||
while (!feof($fp))
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
header('HTTP/1.0 404 Not Found');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an url into a simple html page. Used to display attachments in IE.
|
||||
* this is a workaround for now; might be moved to template system later
|
||||
* direct any complaints to 1 Microsoft Way, Redmond
|
||||
*/
|
||||
function wrap_img_in_html($src, $title)
|
||||
{
|
||||
echo '<!DOCTYPE html>';
|
||||
echo '<html>';
|
||||
echo '<head>';
|
||||
echo '<meta charset="utf-8">';
|
||||
echo '<meta http-equiv="X-UA-Compatible" content="IE=edge">';
|
||||
echo '<title>' . $title . '</title>';
|
||||
echo '</head>';
|
||||
echo '<body>';
|
||||
echo '<div>';
|
||||
echo '<img src="' . $src . '" alt="' . $title . '" />';
|
||||
echo '</div>';
|
||||
echo '</body>';
|
||||
echo '</html>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send file to browser
|
||||
*/
|
||||
function send_file_to_browser($attachment, $upload_dir, $category)
|
||||
{
|
||||
global $user, $db, $phpbb_dispatcher, $phpbb_root_path, $request;
|
||||
|
||||
$filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename'];
|
||||
|
||||
if (!@file_exists($filename))
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
|
||||
// Correct the mime type - we force application/octetstream for all files, except images
|
||||
// Please do not change this, it is a security precaution
|
||||
if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
|
||||
{
|
||||
$attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
|
||||
}
|
||||
|
||||
if (@ob_get_length())
|
||||
{
|
||||
@ob_end_clean();
|
||||
}
|
||||
|
||||
// Now send the File Contents to the Browser
|
||||
$size = @filesize($filename);
|
||||
|
||||
/**
|
||||
* Event to alter attachment before it is sent to browser.
|
||||
*
|
||||
* @event core.send_file_to_browser_before
|
||||
* @var array attachment Attachment data
|
||||
* @var string upload_dir Relative path of upload directory
|
||||
* @var int category Attachment category
|
||||
* @var string filename Path to file, including filename
|
||||
* @var int size File size
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'attachment',
|
||||
'upload_dir',
|
||||
'category',
|
||||
'filename',
|
||||
'size',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.send_file_to_browser_before', compact($vars)));
|
||||
|
||||
// To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work)
|
||||
|
||||
// Check if headers already sent or not able to get the file contents.
|
||||
if (headers_sent() || !@file_exists($filename) || !@is_readable($filename))
|
||||
{
|
||||
// PHP track_errors setting On?
|
||||
if (!empty($php_errormsg))
|
||||
{
|
||||
send_status_line(500, 'Internal Server Error');
|
||||
trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg));
|
||||
}
|
||||
|
||||
send_status_line(500, 'Internal Server Error');
|
||||
trigger_error('UNABLE_TO_DELIVER_FILE');
|
||||
}
|
||||
|
||||
// Make sure the database record for the filesize is correct
|
||||
if ($size > 0 && $size != $attachment['filesize'] && strpos($attachment['physical_filename'], 'thumb_') === false)
|
||||
{
|
||||
// Update database record
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET filesize = ' . (int) $size . '
|
||||
WHERE attach_id = ' . (int) $attachment['attach_id'];
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
// Now the tricky part... let's dance
|
||||
header('Cache-Control: public');
|
||||
|
||||
// Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer.
|
||||
header('Content-Type: ' . $attachment['mimetype']);
|
||||
|
||||
if (phpbb_is_greater_ie_version($user->browser, 7))
|
||||
{
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
}
|
||||
|
||||
if ($category == ATTACHMENT_CATEGORY_FLASH && $request->variable('view', 0) === 1)
|
||||
{
|
||||
// We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline
|
||||
header('Content-Disposition: inline');
|
||||
}
|
||||
else
|
||||
{
|
||||
if (empty($user->browser) || ((strpos(strtolower($user->browser), 'msie') !== false) && !phpbb_is_greater_ie_version($user->browser, 7)))
|
||||
{
|
||||
header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
|
||||
if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false))
|
||||
{
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename'])));
|
||||
if (phpbb_is_greater_ie_version($user->browser, 7) && (strpos($attachment['mimetype'], 'image') !== 0))
|
||||
{
|
||||
header('X-Download-Options: noopen');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the db connection before sending the file etc.
|
||||
file_gc(false);
|
||||
|
||||
if (!set_modified_headers($attachment['filetime'], $user->browser))
|
||||
{
|
||||
// We make sure those have to be enabled manually by defining a constant
|
||||
// because of the potential disclosure of full attachment path
|
||||
// in case support for features is absent in the webserver software.
|
||||
if (defined('PHPBB_ENABLE_X_ACCEL_REDIRECT') && PHPBB_ENABLE_X_ACCEL_REDIRECT)
|
||||
{
|
||||
// X-Accel-Redirect - http://wiki.nginx.org/XSendfile
|
||||
header('X-Accel-Redirect: ' . $user->page['root_script_path'] . $upload_dir . '/' . $attachment['physical_filename']);
|
||||
exit;
|
||||
}
|
||||
else if (defined('PHPBB_ENABLE_X_SENDFILE') && PHPBB_ENABLE_X_SENDFILE && !phpbb_http_byte_range($size))
|
||||
{
|
||||
// X-Sendfile - http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
|
||||
// Lighttpd's X-Sendfile does not support range requests as of 1.4.26
|
||||
// and always requires an absolute path.
|
||||
header('X-Sendfile: ' . dirname(__FILE__) . "/../$upload_dir/{$attachment['physical_filename']}");
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($size)
|
||||
{
|
||||
header("Content-Length: $size");
|
||||
}
|
||||
|
||||
// Try to deliver in chunks
|
||||
@set_time_limit(0);
|
||||
|
||||
$fp = @fopen($filename, 'rb');
|
||||
|
||||
if ($fp !== false)
|
||||
{
|
||||
// Deliver file partially if requested
|
||||
if ($range = phpbb_http_byte_range($size))
|
||||
{
|
||||
fseek($fp, $range['byte_pos_start']);
|
||||
|
||||
send_status_line(206, 'Partial Content');
|
||||
header('Content-Range: bytes ' . $range['byte_pos_start'] . '-' . $range['byte_pos_end'] . '/' . $range['bytes_total']);
|
||||
header('Content-Length: ' . $range['bytes_requested']);
|
||||
|
||||
// First read chunks
|
||||
while (!feof($fp) && ftell($fp) < $range['byte_pos_end'] - 8192)
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
}
|
||||
// Then, read the remainder
|
||||
echo fread($fp, $range['bytes_requested'] % 8192);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!feof($fp))
|
||||
{
|
||||
echo fread($fp, 8192);
|
||||
}
|
||||
}
|
||||
fclose($fp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@readfile($filename);
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a browser friendly UTF-8 encoded filename
|
||||
*/
|
||||
function header_filename($file)
|
||||
{
|
||||
global $request;
|
||||
|
||||
$user_agent = $request->header('User-Agent');
|
||||
|
||||
// There be dragons here.
|
||||
// Not many follows the RFC...
|
||||
if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Konqueror') !== false)
|
||||
{
|
||||
return "filename=" . rawurlencode($file);
|
||||
}
|
||||
|
||||
// follow the RFC for extended filename for the rest
|
||||
return "filename*=UTF-8''" . rawurlencode($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if downloading item is allowed
|
||||
*/
|
||||
function download_allowed()
|
||||
{
|
||||
global $config, $user, $db, $request;
|
||||
|
||||
if (!$config['secure_downloads'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$url = htmlspecialchars_decode($request->header('Referer'));
|
||||
|
||||
if (!$url)
|
||||
{
|
||||
return ($config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
// Split URL into domain and script part
|
||||
$url = @parse_url($url);
|
||||
|
||||
if ($url === false)
|
||||
{
|
||||
return ($config['secure_allow_empty_referer']) ? true : false;
|
||||
}
|
||||
|
||||
$hostname = $url['host'];
|
||||
unset($url);
|
||||
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
$iplist = array();
|
||||
|
||||
if (($ip_ary = @gethostbynamel($hostname)) !== false)
|
||||
{
|
||||
foreach ($ip_ary as $ip)
|
||||
{
|
||||
if ($ip)
|
||||
{
|
||||
$iplist[] = $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for own server...
|
||||
$server_name = $user->host;
|
||||
|
||||
// Forcing server vars is the only way to specify/override the protocol
|
||||
if ($config['force_server_vars'] || !$server_name)
|
||||
{
|
||||
$server_name = $config['server_name'];
|
||||
}
|
||||
|
||||
if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname))
|
||||
{
|
||||
$allowed = true;
|
||||
}
|
||||
|
||||
// Get IP's and Hostnames
|
||||
if (!$allowed)
|
||||
{
|
||||
$sql = 'SELECT site_ip, site_hostname, ip_exclude
|
||||
FROM ' . SITELIST_TABLE;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$site_ip = trim($row['site_ip']);
|
||||
$site_hostname = trim($row['site_hostname']);
|
||||
|
||||
if ($site_ip)
|
||||
{
|
||||
foreach ($iplist as $ip)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
break 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($site_hostname)
|
||||
{
|
||||
if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname))
|
||||
{
|
||||
if ($row['ip_exclude'])
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? false : true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$allowed = ($config['secure_allow_deny']) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the browser has the file already and set the appropriate headers-
|
||||
* @returns false if a resend is in order.
|
||||
*/
|
||||
function set_modified_headers($stamp, $browser)
|
||||
{
|
||||
global $request;
|
||||
|
||||
// let's see if we have to send the file at all
|
||||
$last_load = $request->header('If-Modified-Since') ? strtotime(trim($request->header('If-Modified-Since'))) : false;
|
||||
|
||||
if (strpos(strtolower($browser), 'msie 6.0') === false && !phpbb_is_greater_ie_version($browser, 7))
|
||||
{
|
||||
if ($last_load !== false && $last_load >= $stamp)
|
||||
{
|
||||
send_status_line(304, 'Not Modified');
|
||||
// seems that we need those too ... browsers
|
||||
header('Cache-Control: public');
|
||||
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 31536000) . ' GMT');
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT');
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Garbage Collection
|
||||
*
|
||||
* @param bool $exit Whether to die or not.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function file_gc($exit = true)
|
||||
{
|
||||
global $cache, $db;
|
||||
|
||||
if (!empty($cache))
|
||||
{
|
||||
$cache->unload();
|
||||
}
|
||||
|
||||
$db->sql_close();
|
||||
|
||||
if ($exit)
|
||||
{
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HTTP range support (RFC 2616 Section 14.35)
|
||||
*
|
||||
* Allows browsers to request partial file content
|
||||
* in case a download has been interrupted.
|
||||
*
|
||||
* @param int $filesize the size of the file in bytes we are about to deliver
|
||||
*
|
||||
* @return mixed false if the whole file has to be delivered
|
||||
* associative array on success
|
||||
*/
|
||||
function phpbb_http_byte_range($filesize)
|
||||
{
|
||||
// Only call find_range_request() once.
|
||||
static $request_array;
|
||||
|
||||
if (!$filesize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isset($request_array))
|
||||
{
|
||||
$request_array = phpbb_find_range_request();
|
||||
}
|
||||
|
||||
return (empty($request_array)) ? false : phpbb_parse_range_request($request_array, $filesize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for HTTP range request in request headers.
|
||||
*
|
||||
* @return mixed false if no request found
|
||||
* array of strings containing the requested ranges otherwise
|
||||
* e.g. array(0 => '0-0', 1 => '123-125')
|
||||
*/
|
||||
function phpbb_find_range_request()
|
||||
{
|
||||
global $request;
|
||||
|
||||
$value = $request->header('Range');
|
||||
|
||||
// Make sure range request starts with "bytes="
|
||||
if (strpos($value, 'bytes=') === 0)
|
||||
{
|
||||
// Strip leading 'bytes='
|
||||
// Multiple ranges can be separated by a comma
|
||||
return explode(',', substr($value, 6));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyses a range request array.
|
||||
*
|
||||
* A range request can contain multiple ranges,
|
||||
* we however only handle the first request and
|
||||
* only support requests from a given byte to the end of the file.
|
||||
*
|
||||
* @param array $request_array array of strings containing the requested ranges
|
||||
* @param int $filesize the full size of the file in bytes that has been requested
|
||||
*
|
||||
* @return mixed false if the whole file has to be delivered
|
||||
* associative array on success
|
||||
* byte_pos_start the first byte position, can be passed to fseek()
|
||||
* byte_pos_end the last byte position
|
||||
* bytes_requested the number of bytes requested
|
||||
* bytes_total the full size of the file
|
||||
*/
|
||||
function phpbb_parse_range_request($request_array, $filesize)
|
||||
{
|
||||
$first_byte_pos = -1;
|
||||
$last_byte_pos = -1;
|
||||
|
||||
// Go through all ranges
|
||||
foreach ($request_array as $range_string)
|
||||
{
|
||||
$range = explode('-', trim($range_string));
|
||||
|
||||
// "-" is invalid, "0-0" however is valid and means the very first byte.
|
||||
if (count($range) != 2 || $range[0] === '' && $range[1] === '')
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Substitute defaults
|
||||
if ($range[0] === '')
|
||||
{
|
||||
$range[0] = 0;
|
||||
}
|
||||
|
||||
if ($range[1] === '')
|
||||
{
|
||||
$range[1] = $filesize - 1;
|
||||
}
|
||||
|
||||
if ($last_byte_pos >= 0 && $last_byte_pos + 1 != $range[0])
|
||||
{
|
||||
// We only support contiguous ranges, no multipart stuff :(
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($range[1] && $range[1] < $range[0])
|
||||
{
|
||||
// The requested range contains 0 bytes.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Return bytes from $range[0] to $range[1]
|
||||
if ($first_byte_pos < 0)
|
||||
{
|
||||
$first_byte_pos = (int) $range[0];
|
||||
}
|
||||
|
||||
$last_byte_pos = (int) $range[1];
|
||||
|
||||
if ($first_byte_pos >= $filesize)
|
||||
{
|
||||
// Requested range not satisfiable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust last-byte-pos if it is absent or greater than the content.
|
||||
if ($range[1] === '' || $last_byte_pos >= $filesize)
|
||||
{
|
||||
$last_byte_pos = $filesize - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ($first_byte_pos < 0 || $last_byte_pos < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return array(
|
||||
'byte_pos_start' => $first_byte_pos,
|
||||
'byte_pos_end' => $last_byte_pos,
|
||||
'bytes_requested' => $last_byte_pos - $first_byte_pos + 1,
|
||||
'bytes_total' => $filesize,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments the download count of all provided attachments
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param array|int $ids The attach_id of each attachment
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_increment_downloads($db, $ids)
|
||||
{
|
||||
if (!is_array($ids))
|
||||
{
|
||||
$ids = array($ids);
|
||||
}
|
||||
|
||||
$sql = 'UPDATE ' . ATTACHMENTS_TABLE . '
|
||||
SET download_count = download_count + 1
|
||||
WHERE ' . $db->sql_in_set('attach_id', $ids);
|
||||
$db->sql_query($sql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from a post or topic
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param \phpbb\auth\auth $auth The authentication object
|
||||
* @param int $topic_id The id of the topic that we are downloading from
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_download_handle_forum_auth($db, $auth, $topic_id)
|
||||
{
|
||||
global $phpbb_container;
|
||||
|
||||
$sql_array = array(
|
||||
'SELECT' => 't.topic_visibility, t.forum_id, f.forum_name, f.forum_password, f.parent_id',
|
||||
'FROM' => array(
|
||||
TOPICS_TABLE => 't',
|
||||
FORUMS_TABLE => 'f',
|
||||
),
|
||||
'WHERE' => 't.topic_id = ' . (int) $topic_id . '
|
||||
AND t.forum_id = f.forum_id',
|
||||
);
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
|
||||
|
||||
if ($row && !$phpbb_content_visibility->is_visible('topic', $row['forum_id'], $row))
|
||||
{
|
||||
send_status_line(404, 'Not Found');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
else if ($row && $auth->acl_get('u_download') && $auth->acl_get('f_download', $row['forum_id']))
|
||||
{
|
||||
if ($row['forum_password'])
|
||||
{
|
||||
// Do something else ... ?
|
||||
login_forum_box($row);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles authentication when downloading attachments from PMs
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param \phpbb\auth\auth $auth The authentication object
|
||||
* @param int $user_id The user id
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
function phpbb_download_handle_pm_auth($db, $auth, $user_id, $msg_id)
|
||||
{
|
||||
global $phpbb_dispatcher;
|
||||
|
||||
if (!$auth->acl_get('u_pm_download'))
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('SORRY_AUTH_VIEW_ATTACH');
|
||||
}
|
||||
|
||||
$allowed = phpbb_download_check_pm_auth($db, $user_id, $msg_id);
|
||||
|
||||
/**
|
||||
* Event to modify PM attachments download auth
|
||||
*
|
||||
* @event core.modify_pm_attach_download_auth
|
||||
* @var bool allowed Whether the user is allowed to download from that PM or not
|
||||
* @var int msg_id The id of the PM to download from
|
||||
* @var int user_id The user id for auth check
|
||||
* @since 3.1.11-RC1
|
||||
*/
|
||||
$vars = array('allowed', 'msg_id', 'user_id');
|
||||
extract($phpbb_dispatcher->trigger_event('core.modify_pm_attach_download_auth', compact($vars)));
|
||||
|
||||
if (!$allowed)
|
||||
{
|
||||
send_status_line(403, 'Forbidden');
|
||||
trigger_error('ERROR_NO_ATTACHMENT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a user can download from a particular PM
|
||||
*
|
||||
* @param \phpbb\db\driver\driver_interface $db The database object
|
||||
* @param int $user_id The user id
|
||||
* @param int $msg_id The id of the PM that we are downloading from
|
||||
*
|
||||
* @return bool Whether the user is allowed to download from that PM or not
|
||||
*/
|
||||
function phpbb_download_check_pm_auth($db, $user_id, $msg_id)
|
||||
{
|
||||
// Check if the attachment is within the users scope...
|
||||
$sql = 'SELECT msg_id
|
||||
FROM ' . PRIVMSGS_TO_TABLE . '
|
||||
WHERE msg_id = ' . (int) $msg_id . '
|
||||
AND (
|
||||
user_id = ' . (int) $user_id . '
|
||||
OR author_id = ' . (int) $user_id . '
|
||||
)';
|
||||
$result = $db->sql_query_limit($sql, 1);
|
||||
$allowed = (bool) $db->sql_fetchfield('msg_id');
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the browser is internet explorer version 7+
|
||||
*
|
||||
* @param string $user_agent User agent HTTP header
|
||||
* @param int $version IE version to check against
|
||||
*
|
||||
* @return bool true if internet explorer version is greater than $version
|
||||
*/
|
||||
function phpbb_is_greater_ie_version($user_agent, $version)
|
||||
{
|
||||
if (preg_match('/msie (\d+)/', strtolower($user_agent), $matches))
|
||||
{
|
||||
$ie_version = (int) $matches[1];
|
||||
return ($ie_version > $version);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
904
includes/functions_jabber.php
Normal file
904
includes/functions_jabber.php
Normal file
@@ -0,0 +1,904 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Jabber class from Flyspray project
|
||||
*
|
||||
* @version class.jabber2.php 1595 2008-09-19 (0.9.9)
|
||||
* @copyright 2006 Flyspray.org
|
||||
* @author Florian Schmitz (floele)
|
||||
*
|
||||
* Only slightly modified by Acyd Burn
|
||||
*/
|
||||
class jabber
|
||||
{
|
||||
var $connection = null;
|
||||
var $session = array();
|
||||
var $timeout = 10;
|
||||
|
||||
var $server;
|
||||
var $connect_server;
|
||||
var $port;
|
||||
var $username;
|
||||
var $password;
|
||||
var $use_ssl;
|
||||
var $verify_peer;
|
||||
var $verify_peer_name;
|
||||
var $allow_self_signed;
|
||||
var $resource = 'functions_jabber.phpbb.php';
|
||||
|
||||
var $enable_logging;
|
||||
var $log_array;
|
||||
|
||||
var $features = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $server Jabber server
|
||||
* @param int $port Jabber server port
|
||||
* @param string $username Jabber username or JID
|
||||
* @param string $password Jabber password
|
||||
* @param boold $use_ssl Use ssl
|
||||
* @param bool $verify_peer Verify SSL certificate
|
||||
* @param bool $verify_peer_name Verify Jabber peer name
|
||||
* @param bool $allow_self_signed Allow self signed certificates
|
||||
*/
|
||||
function __construct($server, $port, $username, $password, $use_ssl = false, $verify_peer = true, $verify_peer_name = true, $allow_self_signed = false)
|
||||
{
|
||||
$this->connect_server = ($server) ? $server : 'localhost';
|
||||
$this->port = ($port) ? $port : 5222;
|
||||
|
||||
// Get the server and the username
|
||||
if (strpos($username, '@') === false)
|
||||
{
|
||||
$this->server = $this->connect_server;
|
||||
$this->username = $username;
|
||||
}
|
||||
else
|
||||
{
|
||||
$jid = explode('@', $username, 2);
|
||||
|
||||
$this->username = $jid[0];
|
||||
$this->server = $jid[1];
|
||||
}
|
||||
|
||||
$this->password = $password;
|
||||
$this->use_ssl = ($use_ssl && self::can_use_ssl()) ? true : false;
|
||||
$this->verify_peer = $verify_peer;
|
||||
$this->verify_peer_name = $verify_peer_name;
|
||||
$this->allow_self_signed = $allow_self_signed;
|
||||
|
||||
// Change port if we use SSL
|
||||
if ($this->port == 5222 && $this->use_ssl)
|
||||
{
|
||||
$this->port = 5223;
|
||||
}
|
||||
|
||||
$this->enable_logging = true;
|
||||
$this->log_array = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Able to use the SSL functionality?
|
||||
*/
|
||||
static public function can_use_ssl()
|
||||
{
|
||||
return @extension_loaded('openssl');
|
||||
}
|
||||
|
||||
/**
|
||||
* Able to use TLS?
|
||||
*/
|
||||
static public function can_use_tls()
|
||||
{
|
||||
if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('stream_set_blocking') || !function_exists('stream_get_wrappers'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the encryption stream is supported
|
||||
* Also seem to work without the crypto stream if correctly compiled
|
||||
|
||||
$streams = stream_get_wrappers();
|
||||
|
||||
if (!in_array('streams.crypto', $streams))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the resource which is used. No validation is done here, only escaping.
|
||||
* @param string $name
|
||||
* @access public
|
||||
*/
|
||||
function set_resource($name)
|
||||
{
|
||||
$this->resource = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect
|
||||
*/
|
||||
function connect()
|
||||
{
|
||||
/* if (!$this->check_jid($this->username . '@' . $this->server))
|
||||
{
|
||||
$this->add_to_log('Error: Jabber ID is not valid: ' . $this->username . '@' . $this->server);
|
||||
return false;
|
||||
}*/
|
||||
|
||||
$this->session['ssl'] = $this->use_ssl;
|
||||
|
||||
if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl, $this->verify_peer, $this->verify_peer_name, $this->allow_self_signed))
|
||||
{
|
||||
$this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
|
||||
$this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_to_log('Error: connect() #2');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now we listen what the server has to say...and give appropriate responses
|
||||
$this->response($this->listen());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect
|
||||
*/
|
||||
function disconnect()
|
||||
{
|
||||
if ($this->connected())
|
||||
{
|
||||
// disconnect gracefully
|
||||
if (isset($this->session['sent_presence']))
|
||||
{
|
||||
$this->send_presence('offline', '', true);
|
||||
}
|
||||
|
||||
$this->send('</stream:stream>');
|
||||
$this->session = array();
|
||||
return fclose($this->connection);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connected?
|
||||
*/
|
||||
function connected()
|
||||
{
|
||||
return (is_resource($this->connection) && !feof($this->connection)) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initiates login (using data from contructor, after calling connect())
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function login()
|
||||
{
|
||||
if (!count($this->features))
|
||||
{
|
||||
$this->add_to_log('Error: No feature information from server available.');
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->response($this->features);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send data to the Jabber server
|
||||
* @param string $xml
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function send($xml)
|
||||
{
|
||||
if ($this->connected())
|
||||
{
|
||||
$xml = trim($xml);
|
||||
$this->add_to_log('SEND: '. $xml);
|
||||
return fwrite($this->connection, $xml);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_to_log('Error: Could not send, connection lost (flood?).');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenSocket
|
||||
* @param string $server host to connect to
|
||||
* @param int $port port number
|
||||
* @param bool $use_ssl use ssl or not
|
||||
* @param bool $verify_peer verify ssl certificate
|
||||
* @param bool $verify_peer_name verify peer name
|
||||
* @param bool $allow_self_signed allow self-signed ssl certificates
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function open_socket($server, $port, $use_ssl, $verify_peer, $verify_peer_name, $allow_self_signed)
|
||||
{
|
||||
if (@function_exists('dns_get_record'))
|
||||
{
|
||||
$record = @dns_get_record("_xmpp-client._tcp.$server", DNS_SRV);
|
||||
if (!empty($record) && !empty($record[0]['target']))
|
||||
{
|
||||
$server = $record[0]['target'];
|
||||
}
|
||||
}
|
||||
|
||||
$options = array();
|
||||
|
||||
if ($use_ssl)
|
||||
{
|
||||
$remote_socket = 'ssl://' . $server . ':' . $port;
|
||||
|
||||
// Set ssl context options, see http://php.net/manual/en/context.ssl.php
|
||||
$options['ssl'] = array('verify_peer' => $verify_peer, 'verify_peer_name' => $verify_peer_name, 'allow_self_signed' => $allow_self_signed);
|
||||
}
|
||||
else
|
||||
{
|
||||
$remote_socket = $server . ':' . $port;
|
||||
}
|
||||
|
||||
$socket_context = stream_context_create($options);
|
||||
|
||||
if ($this->connection = @stream_socket_client($remote_socket, $errorno, $errorstr, $this->timeout, STREAM_CLIENT_CONNECT, $socket_context))
|
||||
{
|
||||
stream_set_blocking($this->connection, 0);
|
||||
stream_set_timeout($this->connection, 60);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Apparently an error occurred...
|
||||
$this->add_to_log('Error: open_socket() - ' . $errorstr);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return log
|
||||
*/
|
||||
function get_log()
|
||||
{
|
||||
if ($this->enable_logging && count($this->log_array))
|
||||
{
|
||||
return implode("<br /><br />", $this->log_array);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add information to log
|
||||
*/
|
||||
function add_to_log($string)
|
||||
{
|
||||
if ($this->enable_logging)
|
||||
{
|
||||
$this->log_array[] = utf8_htmlspecialchars($string);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens to the connection until it gets data or the timeout is reached.
|
||||
* Thus, it should only be called if data is expected to be received.
|
||||
* @access public
|
||||
* @return mixed either false for timeout or an array with the received data
|
||||
*/
|
||||
function listen($timeout = 10, $wait = false)
|
||||
{
|
||||
if (!$this->connected())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait for a response until timeout is reached
|
||||
$start = time();
|
||||
$data = '';
|
||||
|
||||
do
|
||||
{
|
||||
$read = trim(fread($this->connection, 4096));
|
||||
$data .= $read;
|
||||
}
|
||||
while (time() <= $start + $timeout && !feof($this->connection) && ($wait || $data == '' || $read != '' || (substr(rtrim($data), -1) != '>')));
|
||||
|
||||
if ($data != '')
|
||||
{
|
||||
$this->add_to_log('RECV: '. $data);
|
||||
return $this->xmlize($data);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->add_to_log('Timeout, no response from server.');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates account registration (based on data used for contructor)
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function register()
|
||||
{
|
||||
if (!isset($this->session['id']) || isset($this->session['jid']))
|
||||
{
|
||||
$this->add_to_log('Error: Cannot initiate registration.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->send("<iq type='get' id='reg_1'><query xmlns='jabber:iq:register'/></iq>");
|
||||
return $this->response($this->listen());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets account presence. No additional info required (default is "online" status)
|
||||
* @param $message online, offline...
|
||||
* @param $type dnd, away, chat, xa or nothing
|
||||
* @param $unavailable set this to true if you want to become unavailable
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function send_presence($message = '', $type = '', $unavailable = false)
|
||||
{
|
||||
if (!isset($this->session['jid']))
|
||||
{
|
||||
$this->add_to_log('ERROR: send_presence() - Cannot set presence at this point, no jid given.');
|
||||
return false;
|
||||
}
|
||||
|
||||
$type = strtolower($type);
|
||||
$type = (in_array($type, array('dnd', 'away', 'chat', 'xa'))) ? '<show>'. $type .'</show>' : '';
|
||||
|
||||
$unavailable = ($unavailable) ? " type='unavailable'" : '';
|
||||
$message = ($message) ? '<status>' . utf8_htmlspecialchars($message) .'</status>' : '';
|
||||
|
||||
$this->session['sent_presence'] = !$unavailable;
|
||||
|
||||
return $this->send("<presence$unavailable>" . $type . $message . '</presence>');
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles all the different XML elements
|
||||
* @param array $xml
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
function response($xml)
|
||||
{
|
||||
if (!is_array($xml) || !count($xml))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// did we get multiple elements? do one after another
|
||||
// array('message' => ..., 'presence' => ...)
|
||||
if (count($xml) > 1)
|
||||
{
|
||||
foreach ($xml as $key => $value)
|
||||
{
|
||||
$this->response(array($key => $value));
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// or even multiple elements of the same type?
|
||||
// array('message' => array(0 => ..., 1 => ...))
|
||||
if (count(reset($xml)) > 1)
|
||||
{
|
||||
foreach (reset($xml) as $value)
|
||||
{
|
||||
$this->response(array(key($xml) => array(0 => $value)));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (key($xml))
|
||||
{
|
||||
case 'stream:stream':
|
||||
// Connection initialised (or after authentication). Not much to do here...
|
||||
|
||||
if (isset($xml['stream:stream'][0]['#']['stream:features']))
|
||||
{
|
||||
// we already got all info we need
|
||||
$this->features = $xml['stream:stream'][0]['#'];
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->features = $this->listen();
|
||||
}
|
||||
|
||||
$second_time = isset($this->session['id']);
|
||||
$this->session['id'] = $xml['stream:stream'][0]['@']['id'];
|
||||
|
||||
if ($second_time)
|
||||
{
|
||||
// If we are here for the second time after TLS, we need to continue logging in
|
||||
return $this->login();
|
||||
}
|
||||
|
||||
// go on with authentication?
|
||||
if (isset($this->features['stream:features'][0]['#']['bind']) || !empty($this->session['tls']))
|
||||
{
|
||||
return $this->response($this->features);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'stream:features':
|
||||
// Resource binding after successful authentication
|
||||
if (isset($this->session['authenticated']))
|
||||
{
|
||||
// session required?
|
||||
$this->session['sess_required'] = isset($xml['stream:features'][0]['#']['session']);
|
||||
|
||||
$this->send("<iq type='set' id='bind_1'>
|
||||
<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'>
|
||||
<resource>" . utf8_htmlspecialchars($this->resource) . '</resource>
|
||||
</bind>
|
||||
</iq>');
|
||||
return $this->response($this->listen());
|
||||
}
|
||||
|
||||
// Let's use TLS if SSL is not enabled and we can actually use it
|
||||
if (!$this->session['ssl'] && self::can_use_tls() && self::can_use_ssl() && isset($xml['stream:features'][0]['#']['starttls']))
|
||||
{
|
||||
$this->add_to_log('Switching to TLS.');
|
||||
$this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n");
|
||||
return $this->response($this->listen());
|
||||
}
|
||||
|
||||
// Does the server support SASL authentication?
|
||||
|
||||
// I hope so, because we do (and no other method).
|
||||
if (isset($xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns']) && $xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-sasl')
|
||||
{
|
||||
// Now decide on method
|
||||
$methods = array();
|
||||
|
||||
foreach ($xml['stream:features'][0]['#']['mechanisms'][0]['#']['mechanism'] as $value)
|
||||
{
|
||||
$methods[] = $value['#'];
|
||||
}
|
||||
|
||||
// we prefer DIGEST-MD5
|
||||
// we don't want to use plain authentication (neither does the server usually) if no encryption is in place
|
||||
|
||||
// http://www.xmpp.org/extensions/attic/jep-0078-1.7.html
|
||||
// The plaintext mechanism SHOULD NOT be used unless the underlying stream is encrypted (using SSL or TLS)
|
||||
// and the client has verified that the server certificate is signed by a trusted certificate authority.
|
||||
|
||||
if (in_array('DIGEST-MD5', $methods))
|
||||
{
|
||||
$this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>");
|
||||
}
|
||||
else if (in_array('PLAIN', $methods) && ($this->session['ssl'] || !empty($this->session['tls'])))
|
||||
{
|
||||
// http://www.ietf.org/rfc/rfc4616.txt (PLAIN SASL Mechanism)
|
||||
$this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>"
|
||||
. base64_encode($this->username . '@' . $this->server . chr(0) . $this->username . chr(0) . $this->password) .
|
||||
'</auth>');
|
||||
}
|
||||
else if (in_array('ANONYMOUS', $methods))
|
||||
{
|
||||
$this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>");
|
||||
}
|
||||
else
|
||||
{
|
||||
// not good...
|
||||
$this->add_to_log('Error: No authentication method supported.');
|
||||
$this->disconnect();
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->response($this->listen());
|
||||
}
|
||||
else
|
||||
{
|
||||
// ok, this is it. bye.
|
||||
$this->add_to_log('Error: Server does not offer SASL authentication.');
|
||||
$this->disconnect();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'challenge':
|
||||
// continue with authentication...a challenge literally -_-
|
||||
$decoded = base64_decode($xml['challenge'][0]['#']);
|
||||
$decoded = $this->parse_data($decoded);
|
||||
|
||||
if (!isset($decoded['digest-uri']))
|
||||
{
|
||||
$decoded['digest-uri'] = 'xmpp/'. $this->server;
|
||||
}
|
||||
|
||||
// better generate a cnonce, maybe it's needed
|
||||
$decoded['cnonce'] = base64_encode(md5(uniqid(mt_rand(), true)));
|
||||
|
||||
// second challenge?
|
||||
if (isset($decoded['rspauth']))
|
||||
{
|
||||
$this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure we only use 'auth' for qop (relevant for $this->encrypt_password())
|
||||
// If the <response> is choking up on the changed parameter we may need to adjust encrypt_password() directly
|
||||
if (isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false)
|
||||
{
|
||||
$decoded['qop'] = 'auth';
|
||||
}
|
||||
|
||||
$response = array(
|
||||
'username' => $this->username,
|
||||
'response' => $this->encrypt_password(array_merge($decoded, array('nc' => '00000001'))),
|
||||
'charset' => 'utf-8',
|
||||
'nc' => '00000001',
|
||||
'qop' => 'auth', // only auth being supported
|
||||
);
|
||||
|
||||
foreach (array('nonce', 'digest-uri', 'realm', 'cnonce') as $key)
|
||||
{
|
||||
if (isset($decoded[$key]))
|
||||
{
|
||||
$response[$key] = $decoded[$key];
|
||||
}
|
||||
}
|
||||
|
||||
$this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" . base64_encode($this->implode_data($response)) . '</response>');
|
||||
}
|
||||
|
||||
return $this->response($this->listen());
|
||||
break;
|
||||
|
||||
case 'failure':
|
||||
$this->add_to_log('Error: Server sent "failure".');
|
||||
$this->disconnect();
|
||||
return false;
|
||||
break;
|
||||
|
||||
case 'proceed':
|
||||
// continue switching to TLS
|
||||
$meta = stream_get_meta_data($this->connection);
|
||||
stream_set_blocking($this->connection, 1);
|
||||
|
||||
if (!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT))
|
||||
{
|
||||
$this->add_to_log('Error: TLS mode change failed.');
|
||||
return false;
|
||||
}
|
||||
|
||||
stream_set_blocking($this->connection, $meta['blocked']);
|
||||
$this->session['tls'] = true;
|
||||
|
||||
// new stream
|
||||
$this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n");
|
||||
$this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
|
||||
|
||||
return $this->response($this->listen());
|
||||
break;
|
||||
|
||||
case 'success':
|
||||
// Yay, authentication successful.
|
||||
$this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n");
|
||||
$this->session['authenticated'] = true;
|
||||
|
||||
// we have to wait for another response
|
||||
return $this->response($this->listen());
|
||||
break;
|
||||
|
||||
case 'iq':
|
||||
// we are not interested in IQs we did not expect
|
||||
if (!isset($xml['iq'][0]['@']['id']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// multiple possibilities here
|
||||
switch ($xml['iq'][0]['@']['id'])
|
||||
{
|
||||
case 'bind_1':
|
||||
$this->session['jid'] = $xml['iq'][0]['#']['bind'][0]['#']['jid'][0]['#'];
|
||||
|
||||
// and (maybe) yet another request to be able to send messages *finally*
|
||||
if ($this->session['sess_required'])
|
||||
{
|
||||
$this->send("<iq to='{$this->server}' type='set' id='sess_1'>
|
||||
<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>
|
||||
</iq>");
|
||||
return $this->response($this->listen());
|
||||
}
|
||||
|
||||
return true;
|
||||
break;
|
||||
|
||||
case 'sess_1':
|
||||
return true;
|
||||
break;
|
||||
|
||||
case 'reg_1':
|
||||
$this->send("<iq type='set' id='reg_2'>
|
||||
<query xmlns='jabber:iq:register'>
|
||||
<username>" . utf8_htmlspecialchars($this->username) . "</username>
|
||||
<password>" . utf8_htmlspecialchars($this->password) . "</password>
|
||||
</query>
|
||||
</iq>");
|
||||
return $this->response($this->listen());
|
||||
break;
|
||||
|
||||
case 'reg_2':
|
||||
// registration end
|
||||
if (isset($xml['iq'][0]['#']['error']))
|
||||
{
|
||||
$this->add_to_log('Warning: Registration failed.');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
break;
|
||||
|
||||
case 'unreg_1':
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
$this->add_to_log('Notice: Received unexpected IQ.');
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'message':
|
||||
// we are only interested in content...
|
||||
if (!isset($xml['message'][0]['#']['body']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$message['body'] = $xml['message'][0]['#']['body'][0]['#'];
|
||||
$message['from'] = $xml['message'][0]['@']['from'];
|
||||
|
||||
if (isset($xml['message'][0]['#']['subject']))
|
||||
{
|
||||
$message['subject'] = $xml['message'][0]['#']['subject'][0]['#'];
|
||||
}
|
||||
$this->session['messages'][] = $message;
|
||||
break;
|
||||
|
||||
default:
|
||||
// hm...don't know this response
|
||||
$this->add_to_log('Notice: Unknown server response (' . key($xml) . ')');
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function send_message($to, $text, $subject = '', $type = 'normal')
|
||||
{
|
||||
if (!isset($this->session['jid']))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!in_array($type, array('chat', 'normal', 'error', 'groupchat', 'headline')))
|
||||
{
|
||||
$type = 'normal';
|
||||
}
|
||||
|
||||
return $this->send("<message from='" . utf8_htmlspecialchars($this->session['jid']) . "' to='" . utf8_htmlspecialchars($to) . "' type='$type' id='" . uniqid('msg') . "'>
|
||||
<subject>" . utf8_htmlspecialchars($subject) . "</subject>
|
||||
<body>" . utf8_htmlspecialchars($text) . "</body>
|
||||
</message>"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts a password as in RFC 2831
|
||||
* @param array $data Needs data from the client-server connection
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function encrypt_password($data)
|
||||
{
|
||||
// let's me think about <challenge> again...
|
||||
foreach (array('realm', 'cnonce', 'digest-uri') as $key)
|
||||
{
|
||||
if (!isset($data[$key]))
|
||||
{
|
||||
$data[$key] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$pack = md5($this->username . ':' . $data['realm'] . ':' . $this->password);
|
||||
|
||||
if (isset($data['authzid']))
|
||||
{
|
||||
$a1 = pack('H32', $pack) . sprintf(':%s:%s:%s', $data['nonce'], $data['cnonce'], $data['authzid']);
|
||||
}
|
||||
else
|
||||
{
|
||||
$a1 = pack('H32', $pack) . sprintf(':%s:%s', $data['nonce'], $data['cnonce']);
|
||||
}
|
||||
|
||||
// should be: qop = auth
|
||||
$a2 = 'AUTHENTICATE:'. $data['digest-uri'];
|
||||
|
||||
return md5(sprintf('%s:%s:%s:%s:%s:%s', md5($a1), $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], md5($a2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,...
|
||||
* @param string $data
|
||||
* @access public
|
||||
* @return array a => b ...
|
||||
*/
|
||||
function parse_data($data)
|
||||
{
|
||||
$data = explode(',', $data);
|
||||
$pairs = array();
|
||||
$key = false;
|
||||
|
||||
foreach ($data as $pair)
|
||||
{
|
||||
$dd = strpos($pair, '=');
|
||||
|
||||
if ($dd)
|
||||
{
|
||||
$key = trim(substr($pair, 0, $dd));
|
||||
$pairs[$key] = trim(trim(substr($pair, $dd + 1)), '"');
|
||||
}
|
||||
else if (strpos(strrev(trim($pair)), '"') === 0 && $key)
|
||||
{
|
||||
// We are actually having something left from "a, b" values, add it to the last one we handled.
|
||||
$pairs[$key] .= ',' . trim(trim($pair), '"');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return $pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* opposite of jabber::parse_data()
|
||||
* @param array $data
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
function implode_data($data)
|
||||
{
|
||||
$return = array();
|
||||
foreach ($data as $key => $value)
|
||||
{
|
||||
$return[] = $key . '="' . $value . '"';
|
||||
}
|
||||
return implode(',', $return);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlize()
|
||||
* @author Hans Anderson
|
||||
* @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
|
||||
*/
|
||||
function xmlize($data, $skip_white = 1, $encoding = 'UTF-8')
|
||||
{
|
||||
$data = trim($data);
|
||||
|
||||
if (substr($data, 0, 5) != '<?xml')
|
||||
{
|
||||
// mod
|
||||
$data = '<root>'. $data . '</root>';
|
||||
}
|
||||
|
||||
$vals = $index = $array = array();
|
||||
$parser = xml_parser_create($encoding);
|
||||
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
||||
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $skip_white);
|
||||
xml_parse_into_struct($parser, $data, $vals, $index);
|
||||
xml_parser_free($parser);
|
||||
|
||||
$i = 0;
|
||||
$tagname = $vals[$i]['tag'];
|
||||
|
||||
$array[$tagname][0]['@'] = (isset($vals[$i]['attributes'])) ? $vals[$i]['attributes'] : array();
|
||||
$array[$tagname][0]['#'] = $this->_xml_depth($vals, $i);
|
||||
|
||||
if (substr($data, 0, 5) != '<?xml')
|
||||
{
|
||||
$array = $array['root'][0]['#'];
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* _xml_depth()
|
||||
* @author Hans Anderson
|
||||
* @copyright Hans Anderson / http://www.hansanderson.com/php/xml/
|
||||
*/
|
||||
function _xml_depth($vals, &$i)
|
||||
{
|
||||
$children = array();
|
||||
|
||||
if (isset($vals[$i]['value']))
|
||||
{
|
||||
array_push($children, $vals[$i]['value']);
|
||||
}
|
||||
|
||||
while (++$i < count($vals))
|
||||
{
|
||||
switch ($vals[$i]['type'])
|
||||
{
|
||||
case 'open':
|
||||
|
||||
$tagname = (isset($vals[$i]['tag'])) ? $vals[$i]['tag'] : '';
|
||||
$size = (isset($children[$tagname])) ? count($children[$tagname]) : 0;
|
||||
|
||||
if (isset($vals[$i]['attributes']))
|
||||
{
|
||||
$children[$tagname][$size]['@'] = $vals[$i]['attributes'];
|
||||
}
|
||||
|
||||
$children[$tagname][$size]['#'] = $this->_xml_depth($vals, $i);
|
||||
|
||||
break;
|
||||
|
||||
case 'cdata':
|
||||
array_push($children, $vals[$i]['value']);
|
||||
break;
|
||||
|
||||
case 'complete':
|
||||
|
||||
$tagname = $vals[$i]['tag'];
|
||||
$size = (isset($children[$tagname])) ? count($children[$tagname]) : 0;
|
||||
$children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? $vals[$i]['value'] : array();
|
||||
|
||||
if (isset($vals[$i]['attributes']))
|
||||
{
|
||||
$children[$tagname][$size]['@'] = $vals[$i]['attributes'];
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'close':
|
||||
return $children;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $children;
|
||||
}
|
||||
}
|
||||
743
includes/functions_mcp.php
Normal file
743
includes/functions_mcp.php
Normal file
@@ -0,0 +1,743 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions used to generate additional URL paramters
|
||||
*/
|
||||
function phpbb_module__url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_notes_url($mode, $module_row)
|
||||
{
|
||||
if ($mode == 'front')
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
global $user_id;
|
||||
return ($user_id) ? "&u=$user_id" : '';
|
||||
}
|
||||
|
||||
function phpbb_module_warn_url($mode, $module_row)
|
||||
{
|
||||
if ($mode == 'front' || $mode == 'list')
|
||||
{
|
||||
global $forum_id;
|
||||
|
||||
return ($forum_id) ? "&f=$forum_id" : '';
|
||||
}
|
||||
|
||||
if ($mode == 'warn_post')
|
||||
{
|
||||
global $forum_id, $post_id;
|
||||
|
||||
$url_extra = ($forum_id) ? "&f=$forum_id" : '';
|
||||
$url_extra .= ($post_id) ? "&p=$post_id" : '';
|
||||
|
||||
return $url_extra;
|
||||
}
|
||||
else
|
||||
{
|
||||
global $user_id;
|
||||
|
||||
return ($user_id) ? "&u=$user_id" : '';
|
||||
}
|
||||
}
|
||||
|
||||
function phpbb_module_main_url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_logs_url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_ban_url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_queue_url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_module_reports_url($mode, $module_row)
|
||||
{
|
||||
return phpbb_extra_url();
|
||||
}
|
||||
|
||||
function phpbb_extra_url()
|
||||
{
|
||||
global $forum_id, $topic_id, $post_id, $report_id, $user_id;
|
||||
|
||||
$url_extra = '';
|
||||
$url_extra .= ($forum_id) ? "&f=$forum_id" : '';
|
||||
$url_extra .= ($topic_id) ? "&t=$topic_id" : '';
|
||||
$url_extra .= ($post_id) ? "&p=$post_id" : '';
|
||||
$url_extra .= ($user_id) ? "&u=$user_id" : '';
|
||||
$url_extra .= ($report_id) ? "&r=$report_id" : '';
|
||||
|
||||
return $url_extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simple topic data
|
||||
*/
|
||||
function phpbb_get_topic_data($topic_ids, $acl_list = false, $read_tracking = false)
|
||||
{
|
||||
global $auth, $db, $config, $user;
|
||||
static $rowset = array();
|
||||
|
||||
$topics = array();
|
||||
|
||||
if (!count($topic_ids))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
// cache might not contain read tracking info, so we can't use it if read
|
||||
// tracking information is requested
|
||||
if (!$read_tracking)
|
||||
{
|
||||
$cache_topic_ids = array_intersect($topic_ids, array_keys($rowset));
|
||||
$topic_ids = array_diff($topic_ids, array_keys($rowset));
|
||||
}
|
||||
else
|
||||
{
|
||||
$cache_topic_ids = array();
|
||||
}
|
||||
|
||||
if (count($topic_ids))
|
||||
{
|
||||
$sql_array = array(
|
||||
'SELECT' => 't.*, f.*',
|
||||
|
||||
'FROM' => array(
|
||||
TOPICS_TABLE => 't',
|
||||
),
|
||||
|
||||
'LEFT_JOIN' => array(
|
||||
array(
|
||||
'FROM' => array(FORUMS_TABLE => 'f'),
|
||||
'ON' => 'f.forum_id = t.forum_id'
|
||||
)
|
||||
),
|
||||
|
||||
'WHERE' => $db->sql_in_set('t.topic_id', $topic_ids)
|
||||
);
|
||||
|
||||
if ($read_tracking && $config['load_db_lastread'])
|
||||
{
|
||||
$sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time';
|
||||
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(TOPICS_TRACK_TABLE => 'tt'),
|
||||
'ON' => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
|
||||
);
|
||||
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(FORUMS_TRACK_TABLE => 'ft'),
|
||||
'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
|
||||
);
|
||||
}
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$rowset[$row['topic_id']] = $row;
|
||||
|
||||
if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$topics[$row['topic_id']] = $row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
|
||||
foreach ($cache_topic_ids as $id)
|
||||
{
|
||||
if (!$acl_list || $auth->acl_gets($acl_list, $rowset[$id]['forum_id']))
|
||||
{
|
||||
$topics[$id] = $rowset[$id];
|
||||
}
|
||||
}
|
||||
|
||||
return $topics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simple post data
|
||||
*/
|
||||
function phpbb_get_post_data($post_ids, $acl_list = false, $read_tracking = false)
|
||||
{
|
||||
global $db, $auth, $config, $user, $phpbb_container;
|
||||
|
||||
$rowset = array();
|
||||
|
||||
if (!count($post_ids))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$sql_array = array(
|
||||
'SELECT' => 'p.*, u.*, t.*, f.*',
|
||||
|
||||
'FROM' => array(
|
||||
USERS_TABLE => 'u',
|
||||
POSTS_TABLE => 'p',
|
||||
TOPICS_TABLE => 't',
|
||||
),
|
||||
|
||||
'LEFT_JOIN' => array(
|
||||
array(
|
||||
'FROM' => array(FORUMS_TABLE => 'f'),
|
||||
'ON' => 'f.forum_id = t.forum_id'
|
||||
)
|
||||
),
|
||||
|
||||
'WHERE' => $db->sql_in_set('p.post_id', $post_ids) . '
|
||||
AND u.user_id = p.poster_id
|
||||
AND t.topic_id = p.topic_id',
|
||||
);
|
||||
|
||||
if ($read_tracking && $config['load_db_lastread'])
|
||||
{
|
||||
$sql_array['SELECT'] .= ', tt.mark_time, ft.mark_time as forum_mark_time';
|
||||
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(TOPICS_TRACK_TABLE => 'tt'),
|
||||
'ON' => 'tt.user_id = ' . $user->data['user_id'] . ' AND t.topic_id = tt.topic_id'
|
||||
);
|
||||
|
||||
$sql_array['LEFT_JOIN'][] = array(
|
||||
'FROM' => array(FORUMS_TRACK_TABLE => 'ft'),
|
||||
'ON' => 'ft.user_id = ' . $user->data['user_id'] . ' AND t.forum_id = ft.forum_id'
|
||||
);
|
||||
}
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $db->sql_query($sql);
|
||||
unset($sql_array);
|
||||
|
||||
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$phpbb_content_visibility->is_visible('post', $row['forum_id'], $row))
|
||||
{
|
||||
// Moderators without the permission to approve post should at least not see them. ;)
|
||||
continue;
|
||||
}
|
||||
|
||||
$rowset[$row['post_id']] = $row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $rowset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simple forum data
|
||||
*/
|
||||
function phpbb_get_forum_data($forum_id, $acl_list = 'f_list', $read_tracking = false)
|
||||
{
|
||||
global $auth, $db, $user, $config, $phpbb_container;
|
||||
|
||||
$rowset = array();
|
||||
|
||||
if (!is_array($forum_id))
|
||||
{
|
||||
$forum_id = array($forum_id);
|
||||
}
|
||||
|
||||
if (!count($forum_id))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
if ($read_tracking && $config['load_db_lastread'])
|
||||
{
|
||||
$read_tracking_join = ' LEFT JOIN ' . FORUMS_TRACK_TABLE . ' ft ON (ft.user_id = ' . $user->data['user_id'] . '
|
||||
AND ft.forum_id = f.forum_id)';
|
||||
$read_tracking_select = ', ft.mark_time';
|
||||
}
|
||||
else
|
||||
{
|
||||
$read_tracking_join = $read_tracking_select = '';
|
||||
}
|
||||
|
||||
$sql = "SELECT f.* $read_tracking_select
|
||||
FROM " . FORUMS_TABLE . " f$read_tracking_join
|
||||
WHERE " . $db->sql_in_set('f.forum_id', $forum_id);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
/* @var $phpbb_content_visibility \phpbb\content_visibility */
|
||||
$phpbb_content_visibility = $phpbb_container->get('content.visibility');
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
if ($acl_list && !$auth->acl_gets($acl_list, $row['forum_id']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
$row['forum_topics_approved'] = $phpbb_content_visibility->get_count('forum_topics', $row, $row['forum_id']);
|
||||
|
||||
$rowset[$row['forum_id']] = $row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $rowset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simple pm data
|
||||
*/
|
||||
function phpbb_get_pm_data($pm_ids)
|
||||
{
|
||||
global $db;
|
||||
|
||||
$rowset = array();
|
||||
|
||||
if (!count($pm_ids))
|
||||
{
|
||||
return array();
|
||||
}
|
||||
|
||||
$sql_array = array(
|
||||
'SELECT' => 'p.*, u.*',
|
||||
|
||||
'FROM' => array(
|
||||
USERS_TABLE => 'u',
|
||||
PRIVMSGS_TABLE => 'p',
|
||||
),
|
||||
|
||||
'WHERE' => $db->sql_in_set('p.msg_id', $pm_ids) . '
|
||||
AND u.user_id = p.author_id',
|
||||
);
|
||||
|
||||
$sql = $db->sql_build_query('SELECT', $sql_array);
|
||||
$result = $db->sql_query($sql);
|
||||
unset($sql_array);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$rowset[$row['msg_id']] = $row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
return $rowset;
|
||||
}
|
||||
|
||||
/**
|
||||
* sorting in mcp
|
||||
*
|
||||
* @param string $where_sql should either be WHERE (default if ommited) or end with AND or OR
|
||||
*
|
||||
* $mode reports and reports_closed: the $where parameters uses aliases p for posts table and r for report table
|
||||
* $mode unapproved_posts: the $where parameters uses aliases p for posts table and t for topic table
|
||||
*/
|
||||
function phpbb_mcp_sorting($mode, &$sort_days_val, &$sort_key_val, &$sort_dir_val, &$sort_by_sql_ary, &$sort_order_sql, &$total_val, $forum_id = 0, $topic_id = 0, $where_sql = 'WHERE')
|
||||
{
|
||||
global $db, $user, $auth, $template, $request, $phpbb_dispatcher;
|
||||
|
||||
$sort_days_val = $request->variable('st', 0);
|
||||
$min_time = ($sort_days_val) ? time() - ($sort_days_val * 86400) : 0;
|
||||
|
||||
switch ($mode)
|
||||
{
|
||||
case 'viewforum':
|
||||
$type = 'topics';
|
||||
$default_key = 't';
|
||||
$default_dir = 'd';
|
||||
|
||||
$sql = 'SELECT COUNT(topic_id) AS total
|
||||
FROM ' . TOPICS_TABLE . "
|
||||
$where_sql forum_id = $forum_id
|
||||
AND topic_type NOT IN (" . POST_ANNOUNCE . ', ' . POST_GLOBAL . ")
|
||||
AND topic_last_post_time >= $min_time";
|
||||
|
||||
if (!$auth->acl_get('m_approve', $forum_id))
|
||||
{
|
||||
$sql .= ' AND topic_visibility = ' . ITEM_APPROVED;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'viewtopic':
|
||||
$type = 'posts';
|
||||
$default_key = 't';
|
||||
$default_dir = 'a';
|
||||
|
||||
$sql = 'SELECT COUNT(post_id) AS total
|
||||
FROM ' . POSTS_TABLE . "
|
||||
$where_sql topic_id = $topic_id
|
||||
AND post_time >= $min_time";
|
||||
|
||||
if (!$auth->acl_get('m_approve', $forum_id))
|
||||
{
|
||||
$sql .= ' AND post_visibility = ' . ITEM_APPROVED;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'unapproved_posts':
|
||||
case 'deleted_posts':
|
||||
$visibility_const = ($mode == 'unapproved_posts') ? array(ITEM_UNAPPROVED, ITEM_REAPPROVE) : ITEM_DELETED;
|
||||
$type = 'posts';
|
||||
$default_key = 't';
|
||||
$default_dir = 'd';
|
||||
$where_sql .= ($topic_id) ? ' p.topic_id = ' . $topic_id . ' AND' : '';
|
||||
|
||||
$sql = 'SELECT COUNT(p.post_id) AS total
|
||||
FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . " t
|
||||
$where_sql " . $db->sql_in_set('p.forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . '
|
||||
AND ' . $db->sql_in_set('p.post_visibility', $visibility_const) .'
|
||||
AND t.topic_id = p.topic_id
|
||||
AND t.topic_visibility <> p.post_visibility';
|
||||
|
||||
if ($min_time)
|
||||
{
|
||||
$sql .= ' AND post_time >= ' . $min_time;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'unapproved_topics':
|
||||
case 'deleted_topics':
|
||||
$visibility_const = ($mode == 'unapproved_topics') ? array(ITEM_UNAPPROVED, ITEM_REAPPROVE) : ITEM_DELETED;
|
||||
$type = 'topics';
|
||||
$default_key = 't';
|
||||
$default_dir = 'd';
|
||||
|
||||
$sql = 'SELECT COUNT(topic_id) AS total
|
||||
FROM ' . TOPICS_TABLE . "
|
||||
$where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_approve'))) . '
|
||||
AND ' . $db->sql_in_set('topic_visibility', $visibility_const);
|
||||
|
||||
if ($min_time)
|
||||
{
|
||||
$sql .= ' AND topic_time >= ' . $min_time;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'pm_reports':
|
||||
case 'pm_reports_closed':
|
||||
case 'reports':
|
||||
case 'reports_closed':
|
||||
$pm = (strpos($mode, 'pm_') === 0) ? true : false;
|
||||
|
||||
$type = ($pm) ? 'pm_reports' : 'reports';
|
||||
$default_key = 't';
|
||||
$default_dir = 'd';
|
||||
$limit_time_sql = ($min_time) ? "AND r.report_time >= $min_time" : '';
|
||||
|
||||
if ($topic_id)
|
||||
{
|
||||
$where_sql .= ' p.topic_id = ' . $topic_id . ' AND ';
|
||||
}
|
||||
else if ($forum_id)
|
||||
{
|
||||
$where_sql .= ' p.forum_id = ' . $forum_id . ' AND ';
|
||||
}
|
||||
else if (!$pm)
|
||||
{
|
||||
$where_sql .= ' ' . $db->sql_in_set('p.forum_id', get_forum_list(array('!f_read', '!m_report')), true, true) . ' AND ';
|
||||
}
|
||||
|
||||
if ($mode == 'reports' || $mode == 'pm_reports')
|
||||
{
|
||||
$where_sql .= ' r.report_closed = 0 AND ';
|
||||
}
|
||||
else
|
||||
{
|
||||
$where_sql .= ' r.report_closed = 1 AND ';
|
||||
}
|
||||
|
||||
if ($pm)
|
||||
{
|
||||
$sql = 'SELECT COUNT(r.report_id) AS total
|
||||
FROM ' . REPORTS_TABLE . ' r, ' . PRIVMSGS_TABLE . " p
|
||||
$where_sql r.post_id = 0
|
||||
AND p.msg_id = r.pm_id
|
||||
$limit_time_sql";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sql = 'SELECT COUNT(r.report_id) AS total
|
||||
FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . " p
|
||||
$where_sql r.pm_id = 0
|
||||
AND p.post_id = r.post_id
|
||||
$limit_time_sql";
|
||||
}
|
||||
break;
|
||||
|
||||
case 'viewlogs':
|
||||
$type = 'logs';
|
||||
$default_key = 't';
|
||||
$default_dir = 'd';
|
||||
|
||||
$sql = 'SELECT COUNT(log_id) AS total
|
||||
FROM ' . LOG_TABLE . "
|
||||
$where_sql " . $db->sql_in_set('forum_id', ($forum_id) ? array($forum_id) : array_intersect(get_forum_list('f_read'), get_forum_list('m_'))) . '
|
||||
AND log_time >= ' . $min_time . '
|
||||
AND log_type = ' . LOG_MOD;
|
||||
break;
|
||||
}
|
||||
|
||||
$sort_key_val = $request->variable('sk', $default_key);
|
||||
$sort_dir_val = $request->variable('sd', $default_dir);
|
||||
$sort_dir_text = array('a' => $user->lang['ASCENDING'], 'd' => $user->lang['DESCENDING']);
|
||||
|
||||
switch ($type)
|
||||
{
|
||||
case 'topics':
|
||||
$limit_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_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 'tt' => $user->lang['TOPIC_TIME'], 'r' => $user->lang['REPLIES'], 's' => $user->lang['SUBJECT'], 'v' => $user->lang['VIEWS']);
|
||||
|
||||
$sort_by_sql_ary = array('a' => 't.topic_first_poster_name', 't' => array('t.topic_last_post_time', 't.topic_last_post_id'), 'tt' => 't.topic_time', 'r' => (($auth->acl_get('m_approve', $forum_id)) ? 't.topic_posts_approved + t.topic_posts_unapproved + t.topic_posts_softdeleted' : 't.topic_posts_approved'), 's' => 't.topic_title', 'v' => 't.topic_views');
|
||||
$limit_time_sql = ($min_time) ? "AND t.topic_last_post_time >= $min_time" : '';
|
||||
break;
|
||||
|
||||
case 'posts':
|
||||
$limit_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_text = array('a' => $user->lang['AUTHOR'], 't' => $user->lang['POST_TIME'], 's' => $user->lang['SUBJECT']);
|
||||
$sort_by_sql_ary = array('a' => 'u.username_clean', 't' => array('p.post_time', 'p.post_id'), 's' => 'p.post_subject');
|
||||
$limit_time_sql = ($min_time) ? "AND p.post_time >= $min_time" : '';
|
||||
break;
|
||||
|
||||
case 'reports':
|
||||
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 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['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
|
||||
$sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => array('p.post_time', 'p.post_id'), 't' => 'r.report_time', 's' => 'p.post_subject');
|
||||
break;
|
||||
|
||||
case 'pm_reports':
|
||||
$limit_days = array(0 => $user->lang['ALL_REPORTS'], 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['AUTHOR'], 'r' => $user->lang['REPORTER'], 'p' => $user->lang['POST_TIME'], 't' => $user->lang['REPORT_TIME'], 's' => $user->lang['SUBJECT']);
|
||||
$sort_by_sql_ary = array('a' => 'u.username_clean', 'r' => 'ru.username', 'p' => 'p.message_time', 't' => 'r.report_time', 's' => 'p.message_subject');
|
||||
break;
|
||||
|
||||
case 'logs':
|
||||
$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_ary = array('u' => 'u.username_clean', 't' => 'l.log_time', 'i' => 'l.log_ip', 'o' => 'l.log_operation');
|
||||
$limit_time_sql = ($min_time) ? "AND l.log_time >= $min_time" : '';
|
||||
break;
|
||||
}
|
||||
|
||||
// Default total to -1 to allow editing by the event
|
||||
$total_val = -1;
|
||||
|
||||
$sort_by_sql = $sort_by_sql_ary;
|
||||
$sort_days = $sort_days_val;
|
||||
$sort_dir = $sort_dir_val;
|
||||
$sort_key = $sort_key_val;
|
||||
$total = $total_val;
|
||||
/**
|
||||
* This event allows you to control the SQL query used to get the total number
|
||||
* of reports the user can access.
|
||||
*
|
||||
* This total is used for the pagination and for displaying the total number
|
||||
* of reports to the user
|
||||
*
|
||||
*
|
||||
* @event core.mcp_sorting_query_before
|
||||
* @var string sql The current SQL search string
|
||||
* @var string mode An id related to the module(s) the user is viewing
|
||||
* @var string type Which kind of information is this being used for displaying. Posts, topics, etc...
|
||||
* @var int forum_id The forum id of the posts the user is trying to access, if not 0
|
||||
* @var int topic_id The topic id of the posts the user is trying to access, if not 0
|
||||
* @var int sort_days The max age of the oldest report to be shown, in days
|
||||
* @var string sort_key The way the user has decided to sort the data.
|
||||
* The valid values must be in the keys of the sort_by_* variables
|
||||
* @var string sort_dir Either 'd' for "DESC" or 'a' for 'ASC' in the SQL query
|
||||
* @var int limit_days The possible max ages of the oldest report for the user to choose, in days.
|
||||
* @var array sort_by_sql SQL text (values) for the possible names of the ways of sorting data (keys).
|
||||
* @var array sort_by_text Language text (values) for the possible names of the ways of sorting data (keys).
|
||||
* @var int min_time Integer with the minimum post time that the user is searching for
|
||||
* @var int limit_time_sql Time limiting options used in the SQL query.
|
||||
* @var int total The total number of reports that exist. Only set if you want to override the result
|
||||
* @var string where_sql Extra information included in the WHERE clause. It must end with "WHERE" or "AND" or "OR".
|
||||
* Set to "WHERE" and set total above -1 to override the total value
|
||||
* @since 3.1.4-RC1
|
||||
*/
|
||||
$vars = array(
|
||||
'sql',
|
||||
'mode',
|
||||
'type',
|
||||
'forum_id',
|
||||
'topic_id',
|
||||
'sort_days',
|
||||
'sort_key',
|
||||
'sort_dir',
|
||||
'limit_days',
|
||||
'sort_by_sql',
|
||||
'sort_by_text',
|
||||
'min_time',
|
||||
'limit_time_sql',
|
||||
'total',
|
||||
'where_sql',
|
||||
);
|
||||
extract($phpbb_dispatcher->trigger_event('core.mcp_sorting_query_before', compact($vars)));
|
||||
$sort_by_sql_ary = $sort_by_sql;
|
||||
$sort_days_val = $sort_days;
|
||||
$sort_key_val = $sort_key;
|
||||
$sort_dir_val = $sort_dir;
|
||||
$total_val = $total;
|
||||
unset($sort_by_sql);
|
||||
unset($sort_days);
|
||||
unset($sort_key);
|
||||
unset($sort_dir);
|
||||
unset($total);
|
||||
|
||||
if (!isset($sort_by_sql_ary[$sort_key_val]))
|
||||
{
|
||||
$sort_key_val = $default_key;
|
||||
}
|
||||
|
||||
$direction = ($sort_dir_val == 'd') ? 'DESC' : 'ASC';
|
||||
|
||||
if (is_array($sort_by_sql_ary[$sort_key_val]))
|
||||
{
|
||||
$sort_order_sql = implode(' ' . $direction . ', ', $sort_by_sql_ary[$sort_key_val]) . ' ' . $direction;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sort_order_sql = $sort_by_sql_ary[$sort_key_val] . ' ' . $direction;
|
||||
}
|
||||
|
||||
$s_limit_days = $s_sort_key = $s_sort_dir = $sort_url = '';
|
||||
gen_sort_selects($limit_days, $sort_by_text, $sort_days_val, $sort_key_val, $sort_dir_val, $s_limit_days, $s_sort_key, $s_sort_dir, $sort_url);
|
||||
|
||||
$template->assign_vars(array(
|
||||
'S_SELECT_SORT_DIR' => $s_sort_dir,
|
||||
'S_SELECT_SORT_KEY' => $s_sort_key,
|
||||
'S_SELECT_SORT_DAYS' => $s_limit_days)
|
||||
);
|
||||
|
||||
if (($sort_days_val && $mode != 'viewlogs') || in_array($mode, array('reports', 'unapproved_topics', 'unapproved_posts', 'deleted_topics', 'deleted_posts')) || $where_sql != 'WHERE')
|
||||
{
|
||||
$result = $db->sql_query($sql);
|
||||
$total_val = (int) $db->sql_fetchfield('total');
|
||||
$db->sql_freeresult($result);
|
||||
}
|
||||
else if ($total_val < -1)
|
||||
{
|
||||
$total_val = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate ids
|
||||
*
|
||||
* @param array &$ids The relevant ids to check
|
||||
* @param string $table The table to find the ids in
|
||||
* @param string $sql_id The ids relevant column name
|
||||
* @param array $acl_list A list of permissions the user need to have
|
||||
* @param mixed $singe_forum Limit to one forum id (int) or the first forum found (true)
|
||||
*
|
||||
* @return mixed False if no ids were able to be retrieved, true if at least one id left.
|
||||
* Additionally, this value can be the forum_id assigned if $single_forum was set.
|
||||
* Therefore checking the result for with !== false is the best method.
|
||||
*/
|
||||
function phpbb_check_ids(&$ids, $table, $sql_id, $acl_list = false, $single_forum = false)
|
||||
{
|
||||
global $db, $auth;
|
||||
|
||||
if (!is_array($ids) || empty($ids))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$sql = "SELECT $sql_id, forum_id FROM $table
|
||||
WHERE " . $db->sql_in_set($sql_id, $ids);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$ids = array();
|
||||
$forum_id = false;
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
if ($acl_list && $row['forum_id'] && !$auth->acl_gets($acl_list, $row['forum_id']))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($acl_list && !$row['forum_id'] && !$auth->acl_getf_global($acl_list))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit forum? If not, just assign the id.
|
||||
if ($single_forum === false)
|
||||
{
|
||||
$ids[] = $row[$sql_id];
|
||||
continue;
|
||||
}
|
||||
|
||||
// Limit forum to a specific forum id?
|
||||
// This can get really tricky, because we do not want to create a failure on global topics. :)
|
||||
if ($row['forum_id'])
|
||||
{
|
||||
if ($single_forum !== true && $row['forum_id'] == (int) $single_forum)
|
||||
{
|
||||
$forum_id = (int) $single_forum;
|
||||
}
|
||||
else if ($forum_id === false)
|
||||
{
|
||||
$forum_id = $row['forum_id'];
|
||||
}
|
||||
|
||||
if ($row['forum_id'] == $forum_id)
|
||||
{
|
||||
$ids[] = $row[$sql_id];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Always add a global topic
|
||||
$ids[] = $row[$sql_id];
|
||||
}
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
if (!count($ids))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If forum id is false and ids populated we may have only global announcements selected (returning 0 because of (int) $forum_id)
|
||||
|
||||
return ($single_forum === false) ? true : (int) $forum_id;
|
||||
}
|
||||
1915
includes/functions_messenger.php
Normal file
1915
includes/functions_messenger.php
Normal file
File diff suppressed because it is too large
Load Diff
1145
includes/functions_module.php
Normal file
1145
includes/functions_module.php
Normal file
File diff suppressed because it is too large
Load Diff
2772
includes/functions_posting.php
Normal file
2772
includes/functions_posting.php
Normal file
File diff suppressed because it is too large
Load Diff
2264
includes/functions_privmsgs.php
Normal file
2264
includes/functions_privmsgs.php
Normal file
File diff suppressed because it is too large
Load Diff
899
includes/functions_transfer.php
Normal file
899
includes/functions_transfer.php
Normal file
@@ -0,0 +1,899 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer class, wrapper for ftp/sftp/ssh
|
||||
*/
|
||||
class transfer
|
||||
{
|
||||
var $connection;
|
||||
var $host;
|
||||
var $port;
|
||||
var $username;
|
||||
var $password;
|
||||
var $timeout;
|
||||
var $root_path;
|
||||
var $tmp_path;
|
||||
var $file_perms;
|
||||
var $dir_perms;
|
||||
|
||||
/**
|
||||
* Constructor - init some basic values
|
||||
*/
|
||||
function __construct()
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$this->file_perms = 0644;
|
||||
$this->dir_perms = 0777;
|
||||
|
||||
// We use the store directory as temporary path to circumvent open basedir restrictions
|
||||
$this->tmp_path = $phpbb_root_path . 'store/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Write file to location
|
||||
*/
|
||||
function write_file($destination_file = '', $contents = '')
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$destination_file = $this->root_path . str_replace($phpbb_root_path, '', $destination_file);
|
||||
|
||||
// need to create a temp file and then move that temp file.
|
||||
// ftp functions can only move files around and can't create.
|
||||
// This means that the users will need to have access to write
|
||||
// temporary files or have write access on a folder within phpBB
|
||||
// like the cache folder. If the user can't do either, then
|
||||
// he/she needs to use the fsock ftp method
|
||||
$temp_name = tempnam($this->tmp_path, 'transfer_');
|
||||
@unlink($temp_name);
|
||||
|
||||
$fp = @fopen($temp_name, 'w');
|
||||
|
||||
if (!$fp)
|
||||
{
|
||||
trigger_error('Unable to create temporary file ' . $temp_name, E_USER_ERROR);
|
||||
}
|
||||
|
||||
@fwrite($fp, $contents);
|
||||
@fclose($fp);
|
||||
|
||||
$result = $this->overwrite_file($temp_name, $destination_file);
|
||||
|
||||
// remove temporary file now
|
||||
@unlink($temp_name);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moving file into location. If the destination file already exists it gets overwritten
|
||||
*/
|
||||
function overwrite_file($source_file, $destination_file)
|
||||
{
|
||||
/**
|
||||
* @todo generally think about overwriting files in another way, by creating a temporary file and then renaming it
|
||||
* @todo check for the destination file existance too
|
||||
*/
|
||||
$this->_delete($destination_file);
|
||||
$result = $this->_put($source_file, $destination_file);
|
||||
$this->_chmod($destination_file, $this->file_perms);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create directory structure
|
||||
*/
|
||||
function make_dir($dir)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$dir = str_replace($phpbb_root_path, '', $dir);
|
||||
$dir = explode('/', $dir);
|
||||
$dirs = '';
|
||||
|
||||
for ($i = 0, $total = count($dir); $i < $total; $i++)
|
||||
{
|
||||
$result = true;
|
||||
|
||||
if (strpos($dir[$i], '.') === 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
$cur_dir = $dir[$i] . '/';
|
||||
|
||||
if (!file_exists($phpbb_root_path . $dirs . $cur_dir))
|
||||
{
|
||||
// create the directory
|
||||
$result = $this->_mkdir($dir[$i]);
|
||||
$this->_chmod($dir[$i], $this->dir_perms);
|
||||
}
|
||||
|
||||
$this->_chdir($this->root_path . $dirs . $dir[$i]);
|
||||
$dirs .= $cur_dir;
|
||||
}
|
||||
|
||||
$this->_chdir($this->root_path);
|
||||
|
||||
/**
|
||||
* @todo stack result into array to make sure every path creation has been taken care of
|
||||
*/
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy file from source location to destination location
|
||||
*/
|
||||
function copy_file($from_loc, $to_loc)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$from_loc = ((strpos($from_loc, $phpbb_root_path) !== 0) ? $phpbb_root_path : '') . $from_loc;
|
||||
$to_loc = $this->root_path . str_replace($phpbb_root_path, '', $to_loc);
|
||||
|
||||
if (!file_exists($from_loc))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = $this->overwrite_file($from_loc, $to_loc);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove file
|
||||
*/
|
||||
function delete_file($file)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$file = $this->root_path . str_replace($phpbb_root_path, '', $file);
|
||||
|
||||
return $this->_delete($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove directory
|
||||
* @todo remove child directories?
|
||||
*/
|
||||
function remove_dir($dir)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$dir = $this->root_path . str_replace($phpbb_root_path, '', $dir);
|
||||
|
||||
return $this->_rmdir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a file or folder
|
||||
*/
|
||||
function rename($old_handle, $new_handle)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$old_handle = $this->root_path . str_replace($phpbb_root_path, '', $old_handle);
|
||||
|
||||
return $this->_rename($old_handle, $new_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a specified file exist...
|
||||
*/
|
||||
function file_exists($directory, $filename)
|
||||
{
|
||||
global $phpbb_root_path;
|
||||
|
||||
$directory = $this->root_path . str_replace($phpbb_root_path, '', $directory);
|
||||
|
||||
$this->_chdir($directory);
|
||||
$result = $this->_ls();
|
||||
|
||||
if ($result !== false && is_array($result))
|
||||
{
|
||||
return (in_array($filename, $result)) ? true : false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open session
|
||||
*/
|
||||
function open_session()
|
||||
{
|
||||
return $this->_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close current session
|
||||
*/
|
||||
function close_session()
|
||||
{
|
||||
return $this->_close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine methods able to be used
|
||||
*/
|
||||
static public function methods()
|
||||
{
|
||||
$methods = array();
|
||||
$disabled_functions = explode(',', @ini_get('disable_functions'));
|
||||
|
||||
if (@extension_loaded('ftp'))
|
||||
{
|
||||
$methods[] = 'ftp';
|
||||
}
|
||||
|
||||
if (!in_array('fsockopen', $disabled_functions))
|
||||
{
|
||||
$methods[] = 'ftp_fsock';
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP transfer class
|
||||
*/
|
||||
class ftp extends transfer
|
||||
{
|
||||
/**
|
||||
* Standard parameters for FTP session
|
||||
*/
|
||||
function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->timeout = $timeout;
|
||||
|
||||
// Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
|
||||
$this->root_path = str_replace('\\', '/', $this->root_path);
|
||||
|
||||
if (!empty($root_path))
|
||||
{
|
||||
$this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
|
||||
}
|
||||
|
||||
// Init some needed values
|
||||
$this->transfer();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests data
|
||||
*/
|
||||
static public function data()
|
||||
{
|
||||
global $user;
|
||||
|
||||
return array(
|
||||
'host' => 'localhost',
|
||||
'username' => 'anonymous',
|
||||
'password' => '',
|
||||
'root_path' => $user->page['root_script_path'],
|
||||
'port' => 21,
|
||||
'timeout' => 10
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init FTP Session
|
||||
* @access private
|
||||
*/
|
||||
function _init()
|
||||
{
|
||||
// connect to the server
|
||||
$this->connection = @ftp_connect($this->host, $this->port, $this->timeout);
|
||||
|
||||
if (!$this->connection)
|
||||
{
|
||||
return 'ERR_CONNECTING_SERVER';
|
||||
}
|
||||
|
||||
// login to the server
|
||||
if (!@ftp_login($this->connection, $this->username, $this->password))
|
||||
{
|
||||
return 'ERR_UNABLE_TO_LOGIN';
|
||||
}
|
||||
|
||||
// attempt to turn pasv mode on
|
||||
@ftp_pasv($this->connection, true);
|
||||
|
||||
// change to the root directory
|
||||
if (!$this->_chdir($this->root_path))
|
||||
{
|
||||
return 'ERR_CHANGING_DIRECTORY';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Directory (MKDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _mkdir($dir)
|
||||
{
|
||||
return @ftp_mkdir($this->connection, $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove directory (RMDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _rmdir($dir)
|
||||
{
|
||||
return @ftp_rmdir($this->connection, $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename file
|
||||
* @access private
|
||||
*/
|
||||
function _rename($old_handle, $new_handle)
|
||||
{
|
||||
return @ftp_rename($this->connection, $old_handle, $new_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change current working directory (CHDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _chdir($dir = '')
|
||||
{
|
||||
if ($dir && $dir !== '/')
|
||||
{
|
||||
if (substr($dir, -1, 1) == '/')
|
||||
{
|
||||
$dir = substr($dir, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return @ftp_chdir($this->connection, $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* change file permissions (CHMOD)
|
||||
* @access private
|
||||
*/
|
||||
function _chmod($file, $perms)
|
||||
{
|
||||
if (function_exists('ftp_chmod'))
|
||||
{
|
||||
$err = @ftp_chmod($this->connection, $perms, $file);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unfortunatly CHMOD is not expecting an octal value...
|
||||
// We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;)
|
||||
$chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file;
|
||||
$err = $this->_site($chmod_cmd);
|
||||
}
|
||||
|
||||
return $err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file to location (PUT)
|
||||
* @access private
|
||||
*/
|
||||
function _put($from_file, $to_file)
|
||||
{
|
||||
// We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
|
||||
$mode = FTP_BINARY;
|
||||
|
||||
$to_dir = dirname($to_file);
|
||||
$to_file = basename($to_file);
|
||||
$this->_chdir($to_dir);
|
||||
|
||||
$result = @ftp_put($this->connection, $to_file, $from_file, $mode);
|
||||
$this->_chdir($this->root_path);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file (DELETE)
|
||||
* @access private
|
||||
*/
|
||||
function _delete($file)
|
||||
{
|
||||
return @ftp_delete($this->connection, $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close ftp session (CLOSE)
|
||||
* @access private
|
||||
*/
|
||||
function _close()
|
||||
{
|
||||
if (!$this->connection)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return @ftp_quit($this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current working directory (CWD)
|
||||
* At the moment not used by parent class
|
||||
* @access private
|
||||
*/
|
||||
function _cwd()
|
||||
{
|
||||
return @ftp_pwd($this->connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of files in a given directory (LS)
|
||||
* @access private
|
||||
*/
|
||||
function _ls($dir = './')
|
||||
{
|
||||
$list = @ftp_nlist($this->connection, $dir);
|
||||
|
||||
// See bug #46295 - Some FTP daemons don't like './'
|
||||
if ($dir === './')
|
||||
{
|
||||
// Let's try some alternatives
|
||||
$list = (empty($list)) ? @ftp_nlist($this->connection, '.') : $list;
|
||||
$list = (empty($list)) ? @ftp_nlist($this->connection, '') : $list;
|
||||
}
|
||||
|
||||
// Return on error
|
||||
if ($list === false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove path if prepended
|
||||
foreach ($list as $key => $item)
|
||||
{
|
||||
// Use same separator for item and dir
|
||||
$item = str_replace('\\', '/', $item);
|
||||
$dir = str_replace('\\', '/', $dir);
|
||||
|
||||
if (!empty($dir) && strpos($item, $dir) === 0)
|
||||
{
|
||||
$item = substr($item, strlen($dir));
|
||||
}
|
||||
|
||||
$list[$key] = $item;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP SITE command (ftp-only function)
|
||||
* @access private
|
||||
*/
|
||||
function _site($command)
|
||||
{
|
||||
return @ftp_site($this->connection, $command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FTP fsock transfer class
|
||||
*/
|
||||
class ftp_fsock extends transfer
|
||||
{
|
||||
var $data_connection;
|
||||
|
||||
/**
|
||||
* Standard parameters for FTP session
|
||||
*/
|
||||
function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10)
|
||||
{
|
||||
$this->host = $host;
|
||||
$this->port = $port;
|
||||
$this->username = $username;
|
||||
$this->password = $password;
|
||||
$this->timeout = $timeout;
|
||||
|
||||
// Make sure $this->root_path is layed out the same way as the $user->page['root_script_path'] value (/ at the end)
|
||||
$this->root_path = str_replace('\\', '/', $this->root_path);
|
||||
|
||||
if (!empty($root_path))
|
||||
{
|
||||
$this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/');
|
||||
}
|
||||
|
||||
// Init some needed values
|
||||
parent::__construct();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests data
|
||||
*/
|
||||
static public function data()
|
||||
{
|
||||
global $user;
|
||||
|
||||
return array(
|
||||
'host' => 'localhost',
|
||||
'username' => 'anonymous',
|
||||
'password' => '',
|
||||
'root_path' => $user->page['root_script_path'],
|
||||
'port' => 21,
|
||||
'timeout' => 10
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Init FTP Session
|
||||
* @access private
|
||||
*/
|
||||
function _init()
|
||||
{
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
|
||||
// connect to the server
|
||||
$this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
|
||||
|
||||
if (!$this->connection || !$this->_check_command())
|
||||
{
|
||||
return 'ERR_CONNECTING_SERVER';
|
||||
}
|
||||
|
||||
@stream_set_timeout($this->connection, $this->timeout);
|
||||
|
||||
// login
|
||||
if (!$this->_send_command('USER', $this->username))
|
||||
{
|
||||
return 'ERR_UNABLE_TO_LOGIN';
|
||||
}
|
||||
|
||||
if (!$this->_send_command('PASS', $this->password))
|
||||
{
|
||||
return 'ERR_UNABLE_TO_LOGIN';
|
||||
}
|
||||
|
||||
// change to the root directory
|
||||
if (!$this->_chdir($this->root_path))
|
||||
{
|
||||
return 'ERR_CHANGING_DIRECTORY';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Directory (MKDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _mkdir($dir)
|
||||
{
|
||||
return $this->_send_command('MKD', $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove directory (RMDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _rmdir($dir)
|
||||
{
|
||||
return $this->_send_command('RMD', $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename File
|
||||
* @access private
|
||||
*/
|
||||
function _rename($old_handle, $new_handle)
|
||||
{
|
||||
$this->_send_command('RNFR', $old_handle);
|
||||
return $this->_send_command('RNTO', $new_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change current working directory (CHDIR)
|
||||
* @access private
|
||||
*/
|
||||
function _chdir($dir = '')
|
||||
{
|
||||
if ($dir && $dir !== '/')
|
||||
{
|
||||
if (substr($dir, -1, 1) == '/')
|
||||
{
|
||||
$dir = substr($dir, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_send_command('CWD', $dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* change file permissions (CHMOD)
|
||||
* @access private
|
||||
*/
|
||||
function _chmod($file, $perms)
|
||||
{
|
||||
// Unfortunatly CHMOD is not expecting an octal value...
|
||||
// We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;)
|
||||
return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload file to location (PUT)
|
||||
* @access private
|
||||
*/
|
||||
function _put($from_file, $to_file)
|
||||
{
|
||||
// We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced)
|
||||
// 'I' == BINARY
|
||||
// 'A' == ASCII
|
||||
if (!$this->_send_command('TYPE', 'I'))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// open the connection to send file over
|
||||
if (!$this->_open_data_connection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_send_command('STOR', $to_file, false);
|
||||
|
||||
// send the file
|
||||
$fp = @fopen($from_file, 'rb');
|
||||
while (!@feof($fp))
|
||||
{
|
||||
@fwrite($this->data_connection, @fread($fp, 4096));
|
||||
}
|
||||
@fclose($fp);
|
||||
|
||||
// close connection
|
||||
$this->_close_data_connection();
|
||||
|
||||
return $this->_check_command();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file (DELETE)
|
||||
* @access private
|
||||
*/
|
||||
function _delete($file)
|
||||
{
|
||||
return $this->_send_command('DELE', $file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close ftp session (CLOSE)
|
||||
* @access private
|
||||
*/
|
||||
function _close()
|
||||
{
|
||||
if (!$this->connection)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->_send_command('QUIT');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current working directory (CWD)
|
||||
* At the moment not used by parent class
|
||||
* @access private
|
||||
*/
|
||||
function _cwd()
|
||||
{
|
||||
$this->_send_command('PWD', '', false);
|
||||
return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return list of files in a given directory (LS)
|
||||
* @access private
|
||||
*/
|
||||
function _ls($dir = './')
|
||||
{
|
||||
if (!$this->_open_data_connection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_send_command('NLST', $dir);
|
||||
|
||||
$list = array();
|
||||
while (!@feof($this->data_connection))
|
||||
{
|
||||
$filename = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512));
|
||||
|
||||
if ($filename !== '')
|
||||
{
|
||||
$list[] = $filename;
|
||||
}
|
||||
}
|
||||
$this->_close_data_connection();
|
||||
|
||||
// Clear buffer
|
||||
$this->_check_command();
|
||||
|
||||
// See bug #46295 - Some FTP daemons don't like './'
|
||||
if ($dir === './' && empty($list))
|
||||
{
|
||||
// Let's try some alternatives
|
||||
$list = $this->_ls('.');
|
||||
|
||||
if (empty($list))
|
||||
{
|
||||
$list = $this->_ls('');
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
// Remove path if prepended
|
||||
foreach ($list as $key => $item)
|
||||
{
|
||||
// Use same separator for item and dir
|
||||
$item = str_replace('\\', '/', $item);
|
||||
$dir = str_replace('\\', '/', $dir);
|
||||
|
||||
if (!empty($dir) && strpos($item, $dir) === 0)
|
||||
{
|
||||
$item = substr($item, strlen($dir));
|
||||
}
|
||||
|
||||
$list[$key] = $item;
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a command to server (FTP fsock only function)
|
||||
* @access private
|
||||
*/
|
||||
function _send_command($command, $args = '', $check = true)
|
||||
{
|
||||
if (!empty($args))
|
||||
{
|
||||
$command = "$command $args";
|
||||
}
|
||||
|
||||
fwrite($this->connection, $command . "\r\n");
|
||||
|
||||
if ($check === true && !$this->_check_command())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a connection to send data (FTP fosck only function)
|
||||
* @access private
|
||||
*/
|
||||
function _open_data_connection()
|
||||
{
|
||||
// Try to find out whether we have a IPv4 or IPv6 (control) connection
|
||||
if (function_exists('stream_socket_get_name'))
|
||||
{
|
||||
$socket_name = stream_socket_get_name($this->connection, true);
|
||||
$server_ip = substr($socket_name, 0, strrpos($socket_name, ':'));
|
||||
}
|
||||
|
||||
if (!isset($server_ip) || preg_match(get_preg_expression('ipv4'), $server_ip))
|
||||
{
|
||||
// Passive mode
|
||||
$this->_send_command('PASV', '', false);
|
||||
|
||||
if (!$ip_port = $this->_check_command(true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// open the connection to start sending the file
|
||||
if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp))
|
||||
{
|
||||
// bad ip and port
|
||||
return false;
|
||||
}
|
||||
|
||||
$temp = explode(',', $temp[0]);
|
||||
$server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3];
|
||||
$server_port = $temp[4] * 256 + $temp[5];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Extended Passive Mode - RFC2428
|
||||
$this->_send_command('EPSV', '', false);
|
||||
|
||||
if (!$epsv_response = $this->_check_command(true))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Response looks like "229 Entering Extended Passive Mode (|||12345|)"
|
||||
// where 12345 is the tcp port for the data connection
|
||||
if (!preg_match('#\(\|\|\|([0-9]+)\|\)#', $epsv_response, $match))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
$server_port = (int) $match[1];
|
||||
|
||||
// fsockopen expects IPv6 address in square brackets
|
||||
$server_ip = "[$server_ip]";
|
||||
}
|
||||
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
|
||||
if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@stream_set_timeout($this->data_connection, $this->timeout);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a connection used to send data
|
||||
* @access private
|
||||
*/
|
||||
function _close_data_connection()
|
||||
{
|
||||
return @fclose($this->data_connection);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to make sure command was successful (FTP fsock only function)
|
||||
* @access private
|
||||
*/
|
||||
function _check_command($return = false)
|
||||
{
|
||||
$response = '';
|
||||
|
||||
do
|
||||
{
|
||||
$result = @fgets($this->connection, 512);
|
||||
$response .= $result;
|
||||
}
|
||||
while (substr($result, 3, 1) !== ' ');
|
||||
|
||||
if (!preg_match('#^[123]#', $response))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return ($return) ? $response : true;
|
||||
}
|
||||
}
|
||||
3759
includes/functions_user.php
Normal file
3759
includes/functions_user.php
Normal file
File diff suppressed because it is too large
Load Diff
250
includes/hooks/index.php
Normal file
250
includes/hooks/index.php
Normal file
@@ -0,0 +1,250 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
if (!defined('IN_PHPBB'))
|
||||
{
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* phpBB Hook Class
|
||||
*/
|
||||
class phpbb_hook
|
||||
{
|
||||
/**
|
||||
* Registered hooks
|
||||
*/
|
||||
var $hooks = array();
|
||||
|
||||
/**
|
||||
* Results returned by functions called
|
||||
*/
|
||||
var $hook_result = array();
|
||||
|
||||
/**
|
||||
* internal pointer
|
||||
*/
|
||||
var $current_hook = NULL;
|
||||
|
||||
/**
|
||||
* Initialize hook class.
|
||||
*
|
||||
* @param array $valid_hooks array containing the hookable functions/methods
|
||||
*/
|
||||
function __construct($valid_hooks)
|
||||
{
|
||||
foreach ($valid_hooks as $_null => $method)
|
||||
{
|
||||
$this->add_hook($method);
|
||||
}
|
||||
|
||||
if (function_exists('phpbb_hook_register'))
|
||||
{
|
||||
phpbb_hook_register($this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register function/method to be called within hook
|
||||
* This function is normally called by the modification/application to attach/register the functions.
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
* @param mixed $hook The replacement function/method to be called. Passing function name or array with object/class definition
|
||||
* @param string $mode Specify the priority/chain mode. 'normal' -> hook gets appended to the chain. 'standalone' -> only the specified hook gets called - later hooks are not able to overwrite this (E_NOTICE is triggered then). 'first' -> hook is called as the first one within the chain. 'last' -> hook is called as the last one within the chain.
|
||||
*/
|
||||
function register($definition, $hook, $mode = 'normal')
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
// Method able to be hooked?
|
||||
if (isset($this->hooks[$class][$function]))
|
||||
{
|
||||
switch ($mode)
|
||||
{
|
||||
case 'standalone':
|
||||
if (!isset($this->hooks[$class][$function]['standalone']))
|
||||
{
|
||||
$this->hooks[$class][$function] = array('standalone' => $hook);
|
||||
}
|
||||
else
|
||||
{
|
||||
trigger_error('Hook not able to be called standalone, previous hook already standalone.', E_NOTICE);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'first':
|
||||
case 'last':
|
||||
$this->hooks[$class][$function][$mode][] = $hook;
|
||||
break;
|
||||
|
||||
case 'normal':
|
||||
default:
|
||||
$this->hooks[$class][$function]['normal'][] = $hook;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calling all functions/methods attached to a specified hook.
|
||||
* Called by the function allowing hooks...
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
* @return bool False if no hook got executed, true otherwise
|
||||
*/
|
||||
function call_hook($definition)
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
if (!empty($this->hooks[$class][$function]))
|
||||
{
|
||||
// Developer tries to call a hooked function within the hooked function...
|
||||
if ($this->current_hook !== NULL && $this->current_hook['class'] === $class && $this->current_hook['function'] === $function)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Call the hook with the arguments attached and store result
|
||||
$arguments = func_get_args();
|
||||
$this->current_hook = array('class' => $class, 'function' => $function);
|
||||
$arguments[0] = &$this;
|
||||
|
||||
// Call the hook chain...
|
||||
if (isset($this->hooks[$class][$function]['standalone']))
|
||||
{
|
||||
$this->hook_result[$class][$function] = call_user_func_array($this->hooks[$class][$function]['standalone'], $arguments);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (array('first', 'normal', 'last') as $mode)
|
||||
{
|
||||
if (!isset($this->hooks[$class][$function][$mode]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($this->hooks[$class][$function][$mode] as $hook)
|
||||
{
|
||||
$this->hook_result[$class][$function] = call_user_func_array($hook, $arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->current_hook = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->current_hook = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result from previously called functions/methods for the same hook
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
* @return mixed False if nothing returned if there is no result, else array('result' => ... )
|
||||
*/
|
||||
function previous_hook_result($definition)
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function]))
|
||||
{
|
||||
return array('result' => $this->hook_result[$class][$function]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the called functions/methods returned something.
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
* @return bool True if results are there, false if not
|
||||
*/
|
||||
function hook_return($definition)
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Give actual result from called functions/methods back.
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
* @return mixed The result
|
||||
*/
|
||||
function hook_return_result($definition)
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
if (!empty($this->hooks[$class][$function]) && isset($this->hook_result[$class][$function]))
|
||||
{
|
||||
$result = $this->hook_result[$class][$function];
|
||||
unset($this->hook_result[$class][$function]);
|
||||
return $result;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new function to the allowed hooks.
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
*/
|
||||
function add_hook($definition)
|
||||
{
|
||||
if (!is_array($definition))
|
||||
{
|
||||
$definition = array('__global', $definition);
|
||||
}
|
||||
|
||||
$this->hooks[$definition[0]][$definition[1]] = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove function from the allowed hooks.
|
||||
*
|
||||
* @param mixed $definition Declaring function (with __FUNCTION__) or class with array(__CLASS__, __FUNCTION__)
|
||||
*/
|
||||
function remove_hook($definition)
|
||||
{
|
||||
$class = (!is_array($definition)) ? '__global' : $definition[0];
|
||||
$function = (!is_array($definition)) ? $definition : $definition[1];
|
||||
|
||||
if (isset($this->hooks[$class][$function]))
|
||||
{
|
||||
unset($this->hooks[$class][$function]);
|
||||
|
||||
if (isset($this->hook_result[$class][$function]))
|
||||
{
|
||||
unset($this->hook_result[$class][$function]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
includes/index.htm
Normal file
10
includes/index.htm
Normal file
@@ -0,0 +1,10 @@
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
</body>
|
||||
</html>
|
||||
36
includes/mcp/info/mcp_ban.php
Normal file
36
includes/mcp/info/mcp_ban.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_ban_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_ban',
|
||||
'title' => 'MCP_BAN',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
36
includes/mcp/info/mcp_logs.php
Normal file
36
includes/mcp/info/mcp_logs.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_logs_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_logs',
|
||||
'title' => 'MCP_LOGS',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
37
includes/mcp/info/mcp_main.php
Normal file
37
includes/mcp/info/mcp_main.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_main_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_main',
|
||||
'title' => 'MCP_MAIN',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
35
includes/mcp/info/mcp_notes.php
Normal file
35
includes/mcp/info/mcp_notes.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_notes_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_notes',
|
||||
'title' => 'MCP_NOTES',
|
||||
'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()
|
||||
{
|
||||
}
|
||||
}
|
||||
36
includes/mcp/info/mcp_pm_reports.php
Normal file
36
includes/mcp/info/mcp_pm_reports.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_pm_reports_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_pm_reports',
|
||||
'title' => 'MCP_PM_REPORTS',
|
||||
'modes' => array(
|
||||
'pm_reports' => array('title' => 'MCP_PM_REPORTS_OPEN', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')),
|
||||
'pm_reports_closed' => array('title' => 'MCP_PM_REPORTS_CLOSED', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')),
|
||||
'pm_report_details' => array('title' => 'MCP_PM_REPORT_DETAILS', 'auth' => 'acl_m_pm_report', 'cat' => array('MCP_REPORTS')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
function install()
|
||||
{
|
||||
}
|
||||
|
||||
function uninstall()
|
||||
{
|
||||
}
|
||||
}
|
||||
38
includes/mcp/info/mcp_queue.php
Normal file
38
includes/mcp/info/mcp_queue.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
* This file is part of the phpBB Forum Software package.
|
||||
*
|
||||
* @copyright (c) phpBB Limited <https://www.phpbb.com>
|
||||
* @license GNU General Public License, version 2 (GPL-2.0)
|
||||
*
|
||||
* For full copyright and license information, please see
|
||||
* the docs/CREDITS.txt file.
|
||||
*
|
||||
*/
|
||||
|
||||
class mcp_queue_info
|
||||
{
|
||||
function module()
|
||||
{
|
||||
return array(
|
||||
'filename' => 'mcp_queue',
|
||||
'title' => 'MCP_QUEUE',
|
||||
'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')),
|
||||
'deleted_topics' => array('title' => 'MCP_QUEUE_DELETED_TOPICS', 'auth' => 'aclf_m_approve', 'cat' => array('MCP_QUEUE')),
|
||||
'deleted_posts' => array('title' => 'MCP_QUEUE_DELETED_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()
|
||||
{
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user