86 lines
3.2 KiB
PHP
86 lines
3.2 KiB
PHP
<?php
|
|
/**
|
|
* Output-buffer based email obfuscation for public frontend pages.
|
|
*/
|
|
|
|
require_once __DIR__ . '/access-guard.php';
|
|
|
|
function raijuEmailObfuscationEnabled(): bool {
|
|
$settingsPath = dirname(__DIR__) . '/content/settings.json';
|
|
if (!is_file($settingsPath)) {
|
|
return false;
|
|
}
|
|
$settings = json_decode((string)file_get_contents($settingsPath), true);
|
|
return is_array($settings) && !empty($settings['privacy']['emailObfuscation']);
|
|
}
|
|
|
|
function raijuEmailObfuscatorIsAdmin(): bool {
|
|
return raijuAccessIsLoggedIn();
|
|
}
|
|
|
|
function raijuEmailFallbackText(string $email): string {
|
|
[$local, $domain] = array_pad(explode('@', $email, 2), 2, '');
|
|
return htmlspecialchars($local . ' [at] ' . str_replace('.', ' [dot] ', $domain), ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
function raijuEmailDataAttrs(string $email, string $query = ''): string {
|
|
$attrs = ' data-raiju-email="' . htmlspecialchars(base64_encode($email), ENT_QUOTES, 'UTF-8') . '"';
|
|
if ($query !== '') {
|
|
$attrs .= ' data-raiju-email-query="' . htmlspecialchars(base64_encode($query), ENT_QUOTES, 'UTF-8') . '"';
|
|
}
|
|
return $attrs;
|
|
}
|
|
|
|
function raijuEmailObfuscateHtml(string $html): string {
|
|
$placeholders = [];
|
|
$html = preg_replace_callback('#<(script|style|textarea|pre|code)\b[^>]*>.*?</\1>#is', function ($m) use (&$placeholders) {
|
|
$key = '%%RAIJU_SKIP_' . count($placeholders) . '%%';
|
|
$placeholders[$key] = $m[0];
|
|
return $key;
|
|
}, $html);
|
|
|
|
$emailPattern = '[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,}';
|
|
|
|
$html = preg_replace_callback('#<a\b([^>]*?)\bhref=(["\'])mailto:([^"\']+)\2([^>]*)>(.*?)</a>#is', function ($m) {
|
|
$before = $m[1];
|
|
$quote = $m[2];
|
|
$mailto = html_entity_decode($m[3], ENT_QUOTES, 'UTF-8');
|
|
$after = $m[4];
|
|
$label = $m[5];
|
|
$parts = explode('?', $mailto, 2);
|
|
$email = rawurldecode($parts[0]);
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
return $m[0];
|
|
}
|
|
$query = isset($parts[1]) ? '?' . $parts[1] : '';
|
|
$attrs = preg_replace('#\s*href=' . preg_quote($quote, '#') . 'mailto:[^"\']+' . preg_quote($quote, '#') . '#i', '', $before . $after);
|
|
$fallback = preg_match('/^\s*' . preg_quote(htmlspecialchars($email, ENT_QUOTES, 'UTF-8'), '/') . '\s*$/i', trim($label))
|
|
? raijuEmailFallbackText($email)
|
|
: $label;
|
|
return '<a href="#"' . $attrs . raijuEmailDataAttrs($email, $query) . '>' . $fallback . '</a>';
|
|
}, $html);
|
|
|
|
$html = preg_replace_callback('/(?<![\/\w.="\'-])(' . $emailPattern . ')(?![\w-])/i', function ($m) {
|
|
$email = $m[1];
|
|
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
|
return $m[0];
|
|
}
|
|
return '<span' . raijuEmailDataAttrs($email) . '>' . raijuEmailFallbackText($email) . '</span>';
|
|
}, $html);
|
|
|
|
if (!empty($placeholders)) {
|
|
$html = strtr($html, $placeholders);
|
|
}
|
|
|
|
return $html;
|
|
}
|
|
|
|
function raijuStartEmailObfuscation(): void {
|
|
static $started = false;
|
|
if ($started || raijuEmailObfuscatorIsAdmin() || !raijuEmailObfuscationEnabled()) {
|
|
return;
|
|
}
|
|
$started = true;
|
|
ob_start('raijuEmailObfuscateHtml');
|
|
}
|