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 ''; } }