First commit

This commit is contained in:
ebassi -
commit e3597abe8e
35 changed files with 2401 additions and 0 deletions

21
acp/link_replacement_info.php Executable file
View file

@ -0,0 +1,21 @@
<?php
namespace pedodev\linkprotection\acp;
class link_replacement_info
{
function module(): array
{
return array(
'filename' => '\pedodev\linkprotection\acp\link_replacement_module',
'title' => 'ACP_LINKPROTECTION_TITLE',
'modes' => array(
'settings' => array(
'title' => 'ACP_LINKPROTECTION_LINKREPLACEMENT',
'auth' => 'ext_pedodev/linkprotection && acl_a_board',
'cat' => ['ACP_LINKPROTECTION_TITLE']
),
),
);
}
}

245
acp/link_replacement_module.php Executable file
View file

@ -0,0 +1,245 @@
<?php
namespace pedodev\linkprotection\acp;
class link_replacement_module
{
private const CIPHER_WHITELIST = array('aes-128-cbc', 'aes-192-cbc', 'aes-256-cbc');
public string $u_action;
private $config, $request, $template, $user, $automatic_link_helper;
private array $automatic_links;
public function main(string $id, string $mode): void
{
global $phpbb_container;
$this->config = $phpbb_container->get('config');
$this->request = $phpbb_container->get('request');
$this->template = $phpbb_container->get('template');
$this->user = $phpbb_container->get('user');
$this->automatic_link_helper = $phpbb_container->get('pedodev.linkprotection.automatic_link_helper');
$this->tpl_name = 'acp_linkreplacement_body';
$this->page_title = $this->user->lang('ACP_LINKPROTECTION_TITLE');
$this->automatic_links = $this->automatic_link_helper->get_automatic_links();
add_form_key('pedodev/linkprotection');
if ($this->request->is_set_post('linkprotection_newkey'))
{
$this->update_key();
}
else if ($this->request->is_set_post('submit'))
{
$this->update_config();
}
$this->get_cipher_list();
$this->get_automatic_link_list();
$this->assign_template_vars();
}
private function check_form_key(): void
{
if (!check_form_key('pedodev/linkprotection'))
{
trigger_error('FORM_INVALID');
}
}
/*
* Called when the user clicks the 'Generate New Key' button
*/
private function update_key(): void
{
$this->check_form_key();
// openssl_cipher_key_length requires PHP >= 8.2
if (function_exists('openssl_cipher_key_length'))
{
$key_length = openssl_cipher_key_length($this->config['pedodev_linkprotection_cipher']);
}
else
{
$key_size = explode('-', $this->config['pedodev_linkprotection_cipher'])[1];
$key_length = $key_size / 8;
}
$new_key = base64_encode(random_bytes($key_length));
$this->config->set('pedodev_linkprotection_key', $new_key);
trigger_error($this->user->lang('ACP_LINKPROTECTION_KEY_UPDATED') . adm_back_link($this->u_action));
}
/*
* Called when the user clicks the 'Submit' button
*/
private function update_config(): void
{
$this->check_form_key();
$this->set_if_positive('pedodev_linkprotection_maxlinks', 'linkprotection_maxlinks');
$cipher = $this->request->variable('linkprotection_cipher', '');
if (!empty($cipher) && in_array($cipher, openssl_get_cipher_methods(), true))
{
$this->config->set('pedodev_linkprotection_cipher', $cipher);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $cipher, 'Cipher') . adm_back_link($this->u_action));
}
$this->config->set('pedodev_linkprotection_manualenabled', $this->request->variable('linkprotection_manualenabled', false));
$this->config->set('pedodev_linkprotection_automaticenabled', $this->request->variable('linkprotection_automaticenabled', false));
if ($this->request->is_set_post('linkprotection_strictmanual'))
{
$this->config->set('pedodev_linkprotection_strictmanual', $this->request->variable('linkprotection_strictmanual', false));
}
if ($this->request->is_set_post('linkprotection_manualtitle'))
{
$manual_title = preg_quote($this->request->variable('linkprotection_manualtitle', ''));
if (!empty($manual_title) && preg_match('#^[\w\. ]+$#', $manual_title))
{
$this->config->set('pedodev_linkprotection_manualtitle', $manual_title);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $manual_title, 'Default Title') . adm_back_link($this->u_action));
}
}
if ($this->request->is_set_post('linkprotection_manuallength'))
{
$this->set_if_positive('pedodev_linkprotection_manuallength', 'linkprotection_manuallength');
}
$manual_tags = preg_quote(rtrim(str_replace(' ', '', $this->request->variable('linkprotection_manualtags', '')), ','));
if (preg_match('#^([\w,]+)?$#', $manual_tags))
{
$this->config->set('pedodev_linkprotection_manualtags', $manual_tags);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $manual_tags, 'Additional Tags') . adm_back_link($this->u_action));
}
if ($this->request->is_set_post('linkprotection_automaticlength'))
{
$this->set_if_positive('pedodev_linkprotection_automaticlength', 'linkprotection_automaticlength');
}
$this->update_automatic_links();
trigger_error($this->user->lang('ACP_LINKPROTECTION_SETTING_SAVED') . adm_back_link($this->u_action));
}
/*
* Make sure the given variable is a positive number, otherwise output an error
*/
private function set_if_positive(string $conf, string $req): void
{
$value = $this->request->variable($req, 0);
if ($value > 0)
{
$this->config->set($conf, $value);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $value, $req) . adm_back_link($this->u_action));
}
}
private function update_automatic_links(): void
{
$counter = 0;
$update_automatic_links = false;
// Delete links
foreach ($this->automatic_links as $url => $title)
{
if ($this->request->is_set_post("linkprotection_automatic_delete_{$counter}"))
{
unset($this->automatic_links[$url]);
$update_automatic_links = true;
}
$counter++;
}
// Add link
if ($this->request->is_set_post('linkprotection_automatic_add_checkbox'))
{
$automatic_link_url = $this->request->variable('linkprotection_automatic_add_url', '');
$automatic_link_title = $this->request->variable('linkprotection_automatic_add_title', '');
if (!empty($automatic_link_url) && !empty($automatic_link_title))
{
$this->automatic_links[$automatic_link_url] = $automatic_link_title;
$update_automatic_links = true;
}
}
if ($update_automatic_links)
{
$this->automatic_link_helper->save_automatic_links($this->automatic_links);
}
}
private function get_cipher_list(): void
{
$cipher_list = array_intersect(
self::CIPHER_WHITELIST,
openssl_get_cipher_methods(),
);
foreach ($cipher_list as $cipher)
{
$this->template->assign_block_vars('cipher_types', [
'TYPE' => $cipher,
'NAME' => strtoupper($cipher),
]);
}
}
private function get_automatic_link_list(): void
{
$id = 0;
foreach ($this->automatic_links as $url => $title)
{
$this->template->assign_block_vars('automatic_links', [
'URL' => $url,
'TITLE' => $title,
'ID' => $id,
]);
$id++;
}
}
private function assign_template_vars(): void
{
$this->template->assign_vars(array(
'U_ACTION' => $this->u_action,
'LINKPROTECTION_MAXLINKS' => $this->config['pedodev_linkprotection_maxlinks'],
'LINKPROTECTION_KEY' => $this->config['pedodev_linkprotection_key'],
'LINKPROTECTION_MANUALENABLED' => $this->config['pedodev_linkprotection_manualenabled'],
'LINKPROTECTION_STRICTMANUAL' => $this->config['pedodev_linkprotection_strictmanual'],
'LINKPROTECTION_MANUALTITLE' => $this->config['pedodev_linkprotection_manualtitle'],
'LINKPROTECTION_MANUALLENGTH' => $this->config['pedodev_linkprotection_manuallength'],
'LINKPROTECTION_MANUALTAGS' => $this->config['pedodev_linkprotection_manualtags'],
'LINKPROTECTION_AUTOMATICENABLED' => $this->config['pedodev_linkprotection_automaticenabled'],
'LINKPROTECTION_AUTOMATICLENGTH' => $this->config['pedodev_linkprotection_automaticlength'],
'LINKPROTECTION_CIPHER' => $this->config['pedodev_linkprotection_cipher'],
));
}
}

21
acp/protected_page_info.php Executable file
View file

@ -0,0 +1,21 @@
<?php
namespace pedodev\linkprotection\acp;
class protected_page_info
{
function module(): array
{
return array(
'filename' => '\pedodev\linkprotection\acp\protected_page_module',
'title' => 'ACP_LINKPROTECTION_TITLE',
'modes' => array(
'settings' => array(
'title' => 'ACP_LINKPROTECTION_PROTECTED_PAGE',
'auth' => 'ext_pedodev/linkprotection && acl_a_board',
'cat' => ['ACP_LINKPROTECTION_TITLE']
),
),
);
}
}

190
acp/protected_page_module.php Executable file
View file

@ -0,0 +1,190 @@
<?php
namespace pedodev\linkprotection\acp;
class protected_page_module
{
public string $u_action;
private $db, $config, $request, $template, $user, $group_helper, $captcha_factory;
private array $group_links;
private array $captcha_list;
function main(string $id, string $mode): void
{
global $phpbb_container;
$this->db = $phpbb_container->get('dbal.conn');
$this->config = $phpbb_container->get('config');
$this->request = $phpbb_container->get('request');
$this->template = $phpbb_container->get('template');
$this->user = $phpbb_container->get('user');
$this->group_helper = $phpbb_container->get('group_helper');
$this->captcha_factory = $phpbb_container->get('captcha.factory');
$this->tpl_name = 'acp_protectedlinkpage_body';
$this->page_title = $this->user->lang('ACP_LINKPROTECTION_TITLE');
$group_links = json_decode($this->config['pedodev_linkprotection_grouplinks'], $associative = true);
$this->group_links = $group_links ? $group_links : array();
$captcha_types = $this->captcha_factory->get_captcha_types();
$this->captcha_list = $captcha_types['available'];
add_form_key('pedodev/linkprotection');
if ($this->request->is_set_post('submit'))
{
$this->update_config();
}
$this->get_captcha_list();
$this->get_group_list();
$this->assign_template_vars();
}
private function check_form_key(): void
{
if (!check_form_key('pedodev/linkprotection'))
{
trigger_error('FORM_INVALID');
}
}
/*
* Called when a user clicks the 'Submit' button
*/
private function update_config(): void
{
$this->check_form_key();
$protected_prefix = $this->request->variable('linkprotection_protectedprefix', '');
if (!empty($protected_prefix) && preg_match('#^[\w]+$#', $protected_prefix))
{
$this->config->set('pedodev_linkprotection_protectedprefix', $protected_prefix);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $protected_prefix, 'Protected Page Prefix') . adm_back_link($this->u_action));
}
$captcha = $this->request->variable('linkprotection_captcha', '');
if (!empty($captcha) && isset($this->captcha_list[$captcha]))
{
$this->config->set('pedodev_linkprotection_captcha', $captcha);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $captcha, 'Captcha') . adm_back_link($this->u_action));
}
$this->config->set('pedodev_linkprotection_showsubmit', $this->request->variable('linkprotection_showsubmit', false));
$this->set_if_positive('pedodev_linkprotection_solvetime', 'linkprotection_solvetime');
$this->config->set('pedodev_linkprotection_multiplelinks', $this->request->variable('linkprotection_multiplelinks', false));
if ($this->request->is_set_post('linkprotection_solveduration'))
{
$this->set_if_positive('pedodev_linkprotection_solveduration', 'linkprotection_solveduration');
}
$this->update_groups();
trigger_error($this->user->lang('ACP_LINKPROTECTION_SETTING_SAVED') . adm_back_link($this->u_action));
}
/*
* Make sure the given variable is a positive number, otherwise output an error
*/
private function set_if_positive(string $conf, string $req): void
{
$value = $this->request->variable($req, 0);
if ($value > 0)
{
$this->config->set($conf, $value);
}
else
{
trigger_error($this->user->lang('ACP_lINKPROTECTION_VALUE_ERROR', $value, $req) . adm_back_link($this->u_action));
}
}
private function update_groups(): void
{
$sql = 'SELECT g.group_id, g.group_name
FROM ' . GROUPS_TABLE . ' g
ORDER BY g.group_type ASC, g.group_name';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$id = (int)$row['group_id'];
$req = 'linkprotection_grouplinks_' . $id;
if ($this->request->is_set_post($req))
{
$num_links = $this->request->variable($req, 0);
if ($num_links > 0)
{
$this->group_links[$id] = $num_links;
}
}
}
$this->db->sql_freeresult($result);
$group_links_encoded = json_encode($this->group_links);
$this->config->set('pedodev_linkprotection_grouplinks', $group_links_encoded);
}
private function get_captcha_list(): void
{
foreach ($this->captcha_list as $type => $name)
{
$this->template->assign_block_vars('captcha_types', [
'TYPE' => $type,
'NAME' => $name,
]);
}
}
private function get_group_list(): void
{
$sql = 'SELECT g.group_id, g.group_name
FROM ' . GROUPS_TABLE . ' g
ORDER BY g.group_type ASC, g.group_name';
$result = $this->db->sql_query($sql);
while ($row = $this->db->sql_fetchrow($result))
{
$id = (int)$row['group_id'];
$name = $this->group_helper->get_name($row['group_name']);
$this->template->assign_block_vars('group_links', [
'ID' => $id,
'NAME' => $name,
'VALUE' => isset($this->group_links[$id]) ? $this->group_links[$id] : 1,
]);
}
$this->db->sql_freeresult($result);
}
private function assign_template_vars(): void
{
$captcha = $this->captcha_factory->get_instance($this->config['pedodev_linkprotection_captcha']);
$this->template->assign_vars(array(
'U_ACTION' => $this->u_action,
'LINKPROTECTION_SHOWSUBMIT' => $this->config['pedodev_linkprotection_showsubmit'],
'LINKPROTECTION_SOLVETIME' => $this->config['pedodev_linkprotection_solvetime'],
'LINKPROTECTION_MULTIPLELINKS' => $this->config['pedodev_linkprotection_multiplelinks'],
'LINKPROTECTION_SOLVEDURATION' => $this->config['pedodev_linkprotection_solveduration'],
'LINKPROTECTION_CAPTCHA' => $this->config['pedodev_linkprotection_captcha'],
'LINKPROTECTION_PROTECTEDPREFIX' => $this->config['pedodev_linkprotection_protectedprefix'],
'LINKPROTECTION_CAPTCHA_PREVIEW' => $captcha->get_demo_template($id = 'captcha'),
));
}
}