mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
120 lines
3.9 KiB
PHP
120 lines
3.9 KiB
PHP
<?php
|
|
|
|
/**
|
|
* EmailObfuscator
|
|
*
|
|
* Obfuscates email addresses as HTML decimal entities so they render
|
|
* correctly in browsers but are invisible to most bots and scrapers.
|
|
*
|
|
* Example:
|
|
* obfuscateEmail('foo@example.com')
|
|
* → foo@example.com
|
|
*
|
|
* obfuscateMailto('foo@example.com')
|
|
* → mailto:foo@ex...
|
|
* (usable inside href="...")
|
|
*
|
|
* obfuscateEmailText('Contact xamxam@erg.be for help')
|
|
* → 'Contact xa...@er... for help'
|
|
* (replaces email addresses found in plain text)
|
|
*
|
|
* Usage:
|
|
* require_once APP_ROOT . '/src/EmailObfuscator.php';
|
|
* echo '<a href="' . EmailObfuscator::mailto('name@domain.com') . '">' . EmailObfuscator::email('name@domain.com') . '</a>';
|
|
*/
|
|
|
|
class EmailObfuscator
|
|
{
|
|
/**
|
|
* Obfuscate an email address for display in HTML content.
|
|
*/
|
|
public static function email(string $address): string
|
|
{
|
|
return self::encode($address);
|
|
}
|
|
|
|
/**
|
|
* Obfuscate a mailto: link for use in an href attribute.
|
|
* Returns 'mailto:' followed by the obfuscated email.
|
|
*/
|
|
public static function mailto(string $address): string
|
|
{
|
|
return 'mailto:' . self::encode($address);
|
|
}
|
|
|
|
/**
|
|
* Replace plain-text email addresses in a string with obfuscated versions.
|
|
* Only replaces addresses that appear as bare text (not already inside HTML entities).
|
|
*/
|
|
public static function emailText(string $text): string
|
|
{
|
|
return preg_replace_callback(
|
|
'/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b/',
|
|
fn (array $m) => self::encode($m[0]),
|
|
$text
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Obfuscate a mailto: URL found in text (e.g. from Markdown or user input).
|
|
* Matches 'mailto:user@domain.com' pattern.
|
|
*/
|
|
public static function mailtoInText(string $text): string
|
|
{
|
|
return preg_replace_callback(
|
|
'/mailto:([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})/i',
|
|
fn (array $m) => 'mailto:' . self::encode($m[1]),
|
|
$text
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Post-process rendered HTML: obfuscate all mailto: links and their
|
|
* visible text (email addresses) so bots can't scrape them.
|
|
*
|
|
* Matches patterns like:
|
|
* <a href="mailto:foo@bar.com">foo@bar.com</a>
|
|
* <a href="mailto:foo@bar.com">some text</a>
|
|
*
|
|
* In the second case, only the href is obfuscated (the link text is kept).
|
|
*/
|
|
public static function obfuscateHtml(string $html): string
|
|
{
|
|
// Match <a> tags whose href starts with mailto:
|
|
return preg_replace_callback(
|
|
'/<a\s[^>]*href="mailto:([^"]+)"[^>]*>(.*?)<\/a>/is',
|
|
function (array $m): string {
|
|
$email = $m[1];
|
|
$linkText = $m[2];
|
|
$obfuscated = self::encode($email);
|
|
|
|
// If the link text is the email itself, replace it too
|
|
$text = strip_tags($linkText);
|
|
if ($text === $email) {
|
|
$linkText = self::encode($linkText);
|
|
}
|
|
|
|
// Rebuild the tag with obfuscated values
|
|
return str_replace(
|
|
['mailto:' . $email, '>' . $m[2] . '<'],
|
|
['mailto:' . $obfuscated, '>' . $linkText . '<'],
|
|
$m[0]
|
|
);
|
|
},
|
|
$html
|
|
);
|
|
}
|
|
|
|
// ── Private ───────────────────────────────────────────────────────────
|
|
|
|
private static function encode(string $s): string
|
|
{
|
|
$out = '';
|
|
$len = strlen($s);
|
|
for ($i = 0; $i < $len; $i++) {
|
|
$out .= '&#' . ord($s[$i]) . ';';
|
|
}
|
|
return $out;
|
|
}
|
|
}
|