213 lines
5.5 KiB
PHP
Executable file
213 lines
5.5 KiB
PHP
Executable file
<?php
|
|
|
|
/*
|
|
* This class is used to replace links in a post whenever it is edited, previewed or created.
|
|
* It handles manual and automatic link replacement
|
|
*/
|
|
|
|
namespace pedodev\linkprotection\core;
|
|
|
|
use phpbb\config\config;
|
|
use pedodev\linkprotection\core\parser;
|
|
use pedodev\linkprotection\core\crypto;
|
|
use pedodev\linkprotection\core\automatic_link_helper;
|
|
use phpbb\auth\auth;
|
|
use phpbb\user;
|
|
use phpbb\language\language;
|
|
|
|
class link_replacer
|
|
{
|
|
private bool $preview;
|
|
private int $link_counter;
|
|
public string $error;
|
|
|
|
public function __construct(
|
|
private config $config,
|
|
private auth $auth,
|
|
private user $user,
|
|
private language $language,
|
|
private parser $parser,
|
|
private crypto $crypto,
|
|
private automatic_link_helper $automatic_link_helper,
|
|
)
|
|
{
|
|
$this->preview = false;
|
|
$this->link_counter = 0;
|
|
$this->error = '';
|
|
}
|
|
|
|
/*
|
|
* Must be called once before encrypting links
|
|
* Sets the user ID and post ID variables in the crypto object
|
|
*/
|
|
public function set_crypto_vars(int $user_id, int $post_id): void
|
|
{
|
|
$this->crypto->set_vars($user_id, $post_id);
|
|
}
|
|
|
|
/*
|
|
* Called when a post is created or previewed.
|
|
* If previewing, replace links with a link to the preview page
|
|
* If not previewing, encrypt and replace links
|
|
*/
|
|
public function find_protect_links(string $message, bool $preview): string
|
|
{
|
|
$this->link_counter = $this->parser->count_encrypted_links($message);
|
|
|
|
$this->preview = $preview;
|
|
|
|
// Limit is set to 1 above the limit so our error will trigger if they try to protect too many links
|
|
$limit = (int)$this->config['pedodev_linkprotection_maxlinks'] + 1;
|
|
|
|
if ($this->config['pedodev_linkprotection_manualenabled'])
|
|
{
|
|
$callback = [$this, 'replace_manual_link'];
|
|
$message = $this->parser->find_replace_manual_links($message, $callback, $limit);
|
|
}
|
|
|
|
if ($this->config['pedodev_linkprotection_automaticenabled'])
|
|
{
|
|
$callback = [$this, 'replace_automatic_link'];
|
|
$message = $this->parser->find_replace_automatic_links($message, $callback, $limit);
|
|
}
|
|
|
|
return $message;
|
|
}
|
|
|
|
/*
|
|
* Called by manual and automatic link replacement
|
|
* Replaces an individual link
|
|
*/
|
|
public function replace_link(array $link_data): string
|
|
{
|
|
if (!ctype_print($link_data['link']))
|
|
{
|
|
return $link_data[0];
|
|
}
|
|
|
|
if ($this->link_limit())
|
|
{
|
|
return $link_data[0];
|
|
}
|
|
|
|
$link_data['title'] = empty($link_data['title']) ? $this->config['pedodev_linkprotection_manualtitle'] : $link_data['title'];
|
|
$link_data['encrypted'] = $this->preview ? 'preview' : $this->crypto->encrypt_link($link_data['link']);
|
|
|
|
if (!isset($link_data['encrypted']))
|
|
{
|
|
return $link_data[0];
|
|
}
|
|
|
|
return $this->parser->get_encrypted_tag($link_data);
|
|
}
|
|
|
|
/*
|
|
* Called when a post is edited
|
|
* Replaces all encrypted links with the original, unprotected links
|
|
*/
|
|
public function find_restore_links(string $message): string
|
|
{
|
|
$callback = [$this, 'restore_link'];
|
|
$limit = (int)$this->config['pedodev_linkprotection_maxlinks'];
|
|
|
|
return $this->parser->find_restore_encrypted_links($message, $callback, $limit);
|
|
}
|
|
|
|
/*
|
|
* Our callback function for find_restore_links. Decrypts and restores an individual link
|
|
*/
|
|
public function restore_link(array $data): string
|
|
{
|
|
if ($this->link_limit())
|
|
{
|
|
return $data[0];
|
|
}
|
|
|
|
$link_data = $this->crypto->decrypt_link($data['encrypted']);
|
|
|
|
if (!$link_data)
|
|
{
|
|
return $data[0];
|
|
}
|
|
|
|
$link_data['title'] = $data['title'];
|
|
|
|
$can_view_original = ($link_data['user_id'] == $this->user->data['user_id']) || $this->auth->acl_get('m_pedodev_linkprotection_vieworiginallinks');
|
|
return $can_view_original ? $this->parser->get_original_text($link_data) : $data[0];
|
|
}
|
|
|
|
/*
|
|
* Called whenever a link is protected
|
|
* Increments the link counter by 1
|
|
* If the link limit is reached, outputs an error and returns true
|
|
* Otherwise returns false
|
|
*/
|
|
private function link_limit(): bool
|
|
{
|
|
$this->link_counter++;
|
|
|
|
if ($this->link_counter > $this->config['pedodev_linkprotection_maxlinks'])
|
|
{
|
|
$this->error = $this->language->lang('LINKPROTECTION_TOO_MANY_LINKS', $this->config['pedodev_linkprotection_maxlinks']);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* Callback function for manual link replacement
|
|
*/
|
|
public function replace_manual_link(array $link_data): string
|
|
{
|
|
if (strlen($link_data['link']) > (int)$this->config['pedodev_linkprotection_manuallength'])
|
|
{
|
|
return $link_data[0];
|
|
}
|
|
|
|
if ($this->config['pedodev_linkprotection_strictmanual'] && !filter_var($link_data['link'], FILTER_VALIDATE_URL))
|
|
{
|
|
return $link_data[0];
|
|
}
|
|
|
|
return $this->replace_link($link_data);
|
|
}
|
|
|
|
/*
|
|
* Callback function for automatic link replacement
|
|
*/
|
|
public function replace_automatic_link(array $link_data): string
|
|
{
|
|
$link = $link_data[0];
|
|
$title = $this->automatic_link_helper->find_substring_match($link);
|
|
|
|
if (empty($title) || strlen($link) > (int)$this->config['pedodev_linkprotection_automaticlength'])
|
|
{
|
|
return $link;
|
|
}
|
|
|
|
$link_data = array_merge($link_data, array(
|
|
'link' => $link,
|
|
'title' => $title,
|
|
));
|
|
|
|
return $this->replace_link($link_data);
|
|
}
|
|
|
|
/*
|
|
* Checks whether user has permission to replace links.
|
|
* If no permission, checks whether a user is trying to manually protect links
|
|
* If trying to protect links without permission, outputs an error message
|
|
*/
|
|
public function check_permission(string $message = ''): bool
|
|
{
|
|
$has_permission = $this->auth->acl_get('u_pedodev_linkprotection_canprotectlinks');
|
|
|
|
if (!$has_permission && $this->parser->find_manual_links($message))
|
|
{
|
|
$this->error = $this->language->lang('LINKPROTECTION_CANNOT_PROTECT_LINKS');
|
|
}
|
|
|
|
return $has_permission;
|
|
}
|
|
}
|