options = $options; $this->security = $security; if (isset($options['enabled']) && $options['enabled']) { add_action('wp_enqueue_scripts', array($this, 'enqueue_scripts')); $this->setup_content_filters(); add_action('wp_footer', array($this, 'add_footer_script')); } } public function enqueue_scripts() { wp_enqueue_script( 'wpnav-redirect-script', WPNAV_LINKS_PLUGIN_URL . 'assets/js/redirect.js', array('jquery'), WPNAV_LINKS_VERSION, true ); wp_localize_script( 'wpnav-redirect-script', 'wpnav_params', array( 'home_url' => home_url(), 'site_domain' => parse_url(home_url(), PHP_URL_HOST), 'exclude_class' => $this->options['exclude_css_class'], 'open_new_tab' => $this->options['open_in_new_tab'], 'redirect_method' => isset($this->options['url_format']) ? $this->options['url_format'] : 'query', 'url_encoding' => 'base64', 'permalink_structure' => get_option('permalink_structure') ? true : false, 'show_external_icon' => !empty($this->options['show_external_icon']), 'whitelist_domains' => $this->get_whitelist_domains(), 'strings' => array( 'external_link' => __('External link', 'wpnav-links'), 'opens_new_window' => __('(opens in a new window)', 'wpnav-links') ) ) ); } private function get_whitelist_domains() { $whitelist = array(); if (!empty($this->options['whitelist_domains'])) { $whitelist = explode("\n", $this->options['whitelist_domains']); $whitelist = array_map('trim', $whitelist); $whitelist = array_filter($whitelist); } return $whitelist; } private function setup_content_filters() { if (isset($this->options['intercept_comments']) && $this->options['intercept_comments']) { add_filter('comment_text', array($this, 'process_content')); } if (isset($this->options['intercept_widgets']) && $this->options['intercept_widgets']) { add_filter('widget_text', array($this, 'process_content')); add_filter('widget_custom_html_content', array($this, 'process_content')); } } public function process_content($content) { if (empty($content)) { return $content; } $dom = new DOMDocument(); libxml_use_internal_errors(true); $dom->loadHTML('
' . $content . '
', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); libxml_clear_errors(); $links = $dom->getElementsByTagName('a'); $modified = false; $links_to_process = array(); foreach ($links as $link) { $links_to_process[] = $link; } foreach ($links_to_process as $link) { $href = $link->getAttribute('href'); if (empty($href)) { continue; } if (!empty($this->options['exclude_css_class'])) { $class = $link->getAttribute('class'); if (strpos($class, $this->options['exclude_css_class']) !== false) { continue; } } if ($this->is_external_link($href)) { if ($this->security->check_whitelist_domain($href)) { continue; } $rel = $link->getAttribute('rel'); $rel_values = empty($rel) ? array() : explode(' ', $rel); $rel_values = array_merge($rel_values, array('nofollow', 'noopener', 'noreferrer')); $rel_values = array_unique($rel_values); $link->setAttribute('rel', implode(' ', $rel_values)); if ($this->options['open_in_new_tab']) { $link->setAttribute('target', '_blank'); $title = $link->getAttribute('title'); if (empty($title)) { $link->setAttribute('title', __('External link (opens in a new window)', 'wpnav-links')); } } $redirect_url = $this->security->get_redirect_url($href); $link->setAttribute('href', $redirect_url); $link->setAttribute('data-wpnav-external', '1'); $modified = true; } } if (!$modified) { return $content; } $new_html = $dom->saveHTML($dom->documentElement); $new_html = preg_replace('/<\?xml encoding="UTF-8"\?>/', '', $new_html); $new_html = preg_replace('/<\/?div>/', '', $new_html); return $new_html; } private function is_external_link($url) { if (strpos($url, '://') === false && strpos($url, '//') !== 0) { return false; } $parsed_url = parse_url($url); if (empty($parsed_url) || !isset($parsed_url['host'])) { return false; } $site_domain = parse_url(home_url(), PHP_URL_HOST); $is_external = ($parsed_url['host'] !== $site_domain); if ($is_external) { if (!empty($this->options['auto_whitelist'])) { if (!empty($this->options['auto_whitelist']['same_root'])) { $site_root = $this->get_root_domain($site_domain); $url_root = $this->get_root_domain($parsed_url['host']); if ($site_root === $url_root) { $is_external = false; } } if ($is_external && !empty($this->options['auto_whitelist']['search_engines'])) { $search_engines = array('google.', 'bing.', 'yahoo.', 'baidu.', 'yandex.', 'duckduckgo.'); foreach ($search_engines as $engine) { if (strpos($parsed_url['host'], $engine) !== false) { $is_external = false; break; } } } } } return $is_external; } private function get_root_domain($domain) { $domain_parts = explode('.', $domain); if (count($domain_parts) > 2) { $tld_part = array_slice($domain_parts, -2, 2); if (in_array($tld_part[0], array('co', 'com', 'net', 'org', 'gov', 'edu'))) { return implode('.', array_slice($domain_parts, -3, 3)); } return implode('.', array_slice($domain_parts, -2, 2)); } return $domain; } public function add_footer_script() { ?>