lowercase bare domains (scheme, www and paths stripped). */
public static function domains($option) {
static $cache = [];
if (!isset($cache[$option])) {
$out = [];
foreach (preg_split('/\r\n|\r|\n/', (string) get_option($option, '')) as $line) {
$line = strtolower(trim($line));
if ($line === '') continue;
$line = preg_replace('~^[a-z]+://~', '', $line);
$line = preg_replace('~[/?#].*$~', '', $line);
$line = preg_replace('/^www\./', '', $line);
if ($line !== '') $out[] = $line;
}
$cache[$option] = array_values(array_unique($out));
}
return $cache[$option];
}
private static function host_in($bare, array $domains) {
foreach ($domains as $domain) {
if ($bare === $domain || substr($bare, -strlen('.' . $domain)) === '.' . $domain) return true;
}
return false;
}
/** the_content filter: decorate every external open tag. */
public static function filter_content($html) {
if (!is_string($html) || $html === '' || stripos($html, '])*)>~i', function ($m) {
return self::decorate_tag($m[0], $m[1]);
}, $html);
}
private static function decorate_tag($tag, $attrs) {
if (!preg_match('~\bhref\s*=\s*(?:"([^"]*)"|\x27([^\x27]*)\x27|([^\s">]+))~i', $attrs, $m)) return $tag;
$href = trim(html_entity_decode($m[1] !== '' ? $m[1] : ((isset($m[2]) && $m[2] !== '') ? $m[2] : ($m[3] ?? '')), ENT_QUOTES | ENT_HTML5, 'UTF-8'));
if ($href === '' || $href[0] === '#') return $tag;
if (preg_match('~^(mailto|tel|javascript|data):~i', $href)) return $tag;
if (strpos($href, '//') === 0) $href = 'https:' . $href;
$host = strtolower((string) wp_parse_url($href, PHP_URL_HOST));
if ($host === '') return $tag; // relative URL = internal
$bare = preg_replace('/^www\./', '', $host);
$home = preg_replace('/^www\./', '', strtolower((string) wp_parse_url(home_url('/'), PHP_URL_HOST)));
if ($bare === $home) return $tag; // internal links are never decorated
$want_blank = get_option('lbraid_ext_new_tab') || self::host_in($bare, self::domains('lbraid_new_tab_domains'));
$want_sponsored = self::host_in($bare, self::domains('lbraid_sponsored_domains'));
$want_nofollow = $want_sponsored
|| ((get_option('lbraid_ext_nofollow') || self::host_in($bare, self::domains('lbraid_nofollow_domains')))
&& !self::host_in($bare, self::domains('lbraid_dofollow_domains')));
if (!$want_blank && !$want_nofollow && !$want_sponsored) return $tag;
// Existing rel: tokens are kept verbatim and only extended.
$rel_raw = null;
if (preg_match('~\brel\s*=\s*(?:"([^"]*)"|\x27([^\x27]*)\x27|([^\s">]+))~i', $attrs, $r)) {
$rel_raw = $r[1] !== '' ? $r[1] : ((isset($r[2]) && $r[2] !== '') ? $r[2] : ($r[3] ?? ''));
}
$tokens = $rel_raw !== null ? preg_split('/\s+/', trim($rel_raw), -1, PREG_SPLIT_NO_EMPTY) : [];
$lower = array_map('strtolower', $tokens);
$has_target = (bool) preg_match('~\btarget\s*=~i', $attrs);
$adding_blank = $want_blank && !$has_target;
$add = [];
if ($want_nofollow && !in_array('nofollow', $lower, true)) $add[] = 'nofollow';
if ($want_sponsored && !in_array('sponsored', $lower, true)) $add[] = 'sponsored';
if ($adding_blank && !in_array('noopener', $lower, true)) $add[] = 'noopener';
if (!$add && !$adding_blank) return $tag;
$new_attrs = $attrs;
if ($add) {
$value = implode(' ', array_merge($tokens, $add));
if ($rel_raw !== null) {
$position = strpos($new_attrs, $r[0]);
$new_attrs = substr($new_attrs, 0, $position) . 'rel="' . esc_attr($value) . '"' . substr($new_attrs, $position + strlen($r[0]));
} else {
$new_attrs .= ' rel="' . esc_attr($value) . '"';
}
}
if ($adding_blank) $new_attrs .= ' target="_blank"';
return '';
}
}