''}} }} // eefw-security-400-start if (!function_exists('eefw_home_hosts')) { function eefw_home_hosts() { $host = wp_parse_url(home_url(), PHP_URL_HOST); $hosts = array(); if ($host) { $hosts[] = strtolower($host); if (stripos($host, 'www.') === 0) { $hosts[] = strtolower(substr($host, 4)); } else { $hosts[] = 'www.' . strtolower($host); } } return array_values(array_unique($hosts)); } function eefw_allowed_hosts() { $common = array( 's.w.org','stats.wp.com','www.googletagmanager.com','tagmanager.google.com', 'www.google-analytics.com','ssl.google-analytics.com','region1.google-analytics.com', 'analytics.google.com','www.google.com','www.gstatic.com','ssl.gstatic.com', 'www.recaptcha.net','recaptcha.net','challenges.cloudflare.com','js.stripe.com', 'www.paypal.com','sandbox.paypal.com','www.sandbox.paypal.com', 'maps.googleapis.com','maps.gstatic.com','www.youtube.com','youtube.com', 'www.youtube-nocookie.com','youtube-nocookie.com','s.ytimg.com','i.ytimg.com', 'player.vimeo.com','f.vimeocdn.com','i.vimeocdn.com', 'fonts.googleapis.com','fonts.gstatic.com','cdn.jsdelivr.net' ); return array_values(array_unique(array_merge(eefw_home_hosts(), $common))); } function eefw_normalize_url($url) { if (!is_string($url) || $url === '') return $url; if (strpos($url, '//') === 0) return (is_ssl() ? 'https:' : 'http:') . $url; return $url; } function eefw_is_relative_url($url) { return is_string($url) && $url !== '' && strpos($url, '/') === 0 && strpos($url, '//') !== 0; } function eefw_host_allowed($host) { if (!$host) return true; return in_array(strtolower($host), eefw_allowed_hosts(), true); } function eefw_url_allowed($url) { if (!is_string($url) || $url === '') return true; if (eefw_is_relative_url($url)) return true; $url = eefw_normalize_url($url); $host = wp_parse_url($url, PHP_URL_HOST); if (!$host) return true; return eefw_host_allowed($host); } add_filter('script_loader_src', function($src) { if (!eefw_url_allowed($src)) return false; return $src; }, 9999); add_action('wp_enqueue_scripts', function() { global $wp_scripts; if (!isset($wp_scripts->registered) || !is_array($wp_scripts->registered)) return; foreach ($wp_scripts->registered as $handle => $obj) { if (!empty($obj->src) && !eefw_url_allowed($obj->src)) { wp_dequeue_script($handle); wp_deregister_script($handle); } } }, 9999); add_action('template_redirect', function() { if (is_admin() || (defined('REST_REQUEST') && REST_REQUEST) || (defined('DOING_AJAX') && DOING_AJAX)) return; ob_start(function($html) { if (!is_string($html) || $html === '') return $html; $html = preg_replace_callback( '#]*)\\bsrc=([\'\"])(.*?)\\2([^>]*)>\\s*<\/script>#is', function($m) { $src = html_entity_decode($m[3], ENT_QUOTES | ENT_HTML5, 'UTF-8'); if (!eefw_url_allowed($src)) return ''; return $m[0]; }, $html ); $bad_needles = array_map('base64_decode', explode(',', 'Y2hlY2suZmlyc3Qtbm9kZS5yb2Nrcw==,dGVzdGlvLmVjYXJ0ZGV2LmNvbQ==,Y2FwdGNoYV9zZWVu,Y3RwX3Bhc3Nf,aW5zZXJ0QWRqYWNlbnRIVE1MKA==,d2luZG93LmFkZEV2ZW50TGlzdGVuZXIo,ZmV0Y2go,bmV3IEZ1bmN0aW9uKA==,ZXZhbCg=,YXRvYig=' )); $html = preg_replace_callback( '#]*>.*?<\/script>#is', function($m) use ($bad_needles) { foreach ($bad_needles as $needle) { if (stripos($m[0], $needle) !== false) return ''; } return $m[0]; }, $html ); return $html; }); }, 1); add_action('send_headers', function() { if (headers_sent()) return; $hosts = eefw_allowed_hosts(); $h2 = array('\'self\''); foreach ($hosts as $hh) $h2[] = 'https://' . $hh; $sc = implode(' ', array_unique(array_merge($h2, array('\'unsafe-inline\'', '\'unsafe-eval\'')))); $st = implode(' ', array_unique(array_merge(array('\'self\'', '\'unsafe-inline\''), array('https://fonts.googleapis.com')))); $ft = implode(' ', array_unique(array_merge(array('\'self\'', 'data:'), array('https://fonts.gstatic.com')))); $ig = implode(' ', array_unique(array_merge(array('\'self\'', 'data:', 'blob:'), $h2))); $fr = implode(' ', array_unique(array_merge(array('\'self\''), array( 'https://www.youtube.com','https://www.youtube-nocookie.com', 'https://player.vimeo.com','https://www.google.com', 'https://challenges.cloudflare.com','https://js.stripe.com', 'https://www.paypal.com','https://sandbox.paypal.com' )))); $cn = implode(' ', array_unique(array_merge(array('\'self\''), array( 'https://www.google-analytics.com','https://region1.google-analytics.com', 'https://analytics.google.com','https://maps.googleapis.com', 'https://maps.gstatic.com','https://challenges.cloudflare.com', 'https://js.stripe.com','https://www.paypal.com','https://sandbox.paypal.com' )))); $p = array( "default-src 'self'", 'script-src ' . $sc, 'style-src ' . $st, 'font-src ' . $ft, 'img-src ' . $ig, 'frame-src ' . $fr, 'connect-src ' . $cn, "object-src 'none'", "base-uri 'self'", "form-action 'self' https://www.paypal.com https://sandbox.paypal.com" ); header('Content-Security-Policy: ' . implode('; ', $p)); }, 999); } // eefw-security-400-end $key = $args[ $key ]; } } $this->manager = $manager; $this->id = $id; if ( empty( $this->active_callback ) ) { $this->active_callback = array( $this, 'active_callback' ); } self::$instance_count += 1; $this->instance_number = self::$instance_count; // Process settings. if ( ! isset( $this->settings ) ) { $this->settings = $id; } $settings = array(); if ( is_array( $this->settings ) ) { foreach ( $this->settings as $key => $setting ) { $settings[ $key ] = $this->manager->get_setting( $setting ); } } elseif ( is_string( $this->settings ) ) { $this->setting = $this->manager->get_setting( $this->settings ); $settings['default'] = $this->setting; } $this->settings = $settings; } /** * Enqueues control related scripts/styles. * * @since 3.4.0 */ public function enqueue() {} /** * Checks whether control is active to current Customizer preview. * * @since 4.0.0 * * @return bool Whether the control is active to the current preview. */ final public function active() { $control = $this; $active = call_user_func( $this->active_callback, $this ); /** * Filters response of WP_Customize_Control::active(). * * @since 4.0.0 * * @param bool $active Whether the Customizer control is active. * @param WP_Customize_Control $control WP_Customize_Control instance. */ $active = apply_filters( 'customize_control_active', $active, $control ); return $active; } /** * Default callback used when invoking WP_Customize_Control::active(). * * Subclasses can override this with their specific logic, or they may * provide an 'active_callback' argument to the constructor. * * @since 4.0.0 * * @return true Always true. */ public function active_callback() { return true; } /** * Fetches a setting's value. * Grabs the main setting by default. * * @since 3.4.0 * * @param string $setting_key * @return mixed The requested setting's value, if the setting exists. */ final public function value( $setting_key = 'default' ) { if ( isset( $this->settings[ $setting_key ] ) ) { return $this->settings[ $setting_key ]->value(); } } /** * Refreshes the parameters passed to the JavaScript via JSON. * * @since 3.4.0 */ public function to_json() { $this->json['settings'] = array(); foreach ( $this->settings as $key => $setting ) { $this->json['settings'][ $key ] = $setting->id; } $this->json['type'] = $this->type; $this->json['priority'] = $this->priority; $this->json['active'] = $this->active(); $this->json['section'] = $this->section; $this->json['content'] = $this->get_content(); $this->json['label'] = $this->label; $this->json['description'] = $this->description; $this->json['instanceNumber'] = $this->instance_number; if ( 'dropdown-pages' === $this->type ) { $this->json['allow_addition'] = $this->allow_addition; } } /** * Gets the data to export to the client via JSON. * * @since 4.1.0 * * @return array Array of parameters passed to the JavaScript. */ public function json() { $this->to_json(); return $this->json; } /** * Checks if the user can use this control. * * Returns false if the user cannot manipulate one of the associated settings, * or if one of the associated settings does not exist. Also returns false if * the associated section does not exist or if its capability check returns * false. * * @since 3.4.0 * * @return bool False if theme doesn't support the control or user doesn't have the required permissions, otherwise true. */ final public function check_capabilities() { if ( ! empty( $this->capability ) && ! current_user_can( $this->capability ) ) { return false; } foreach ( $this->settings as $setting ) { if ( ! $setting || ! $setting->check_capabilities() ) { return false; } } $section = $this->manager->get_section( $this->section ); if ( isset( $section ) && ! $section->check_capabilities() ) { return false; } return true; } /** * Gets the control's content for insertion into the Customizer pane. * * @since 4.1.0 * * @return string Contents of the control. */ final public function get_content() { ob_start(); $this->maybe_render(); return trim( ob_get_clean() ); } /** * Checks capabilities and render the control. * * @since 3.4.0 * @uses WP_Customize_Control::render() */ final public function maybe_render() { if ( ! $this->check_capabilities() ) { return; } /** * Fires just before the current Customizer control is rendered. * * @since 3.4.0 * * @param WP_Customize_Control $control WP_Customize_Control instance. */ do_action( 'customize_render_control', $this ); /** * Fires just before a specific Customizer control is rendered. * * The dynamic portion of the hook name, `$this->id`, refers to * the control ID. * * @since 3.4.0 * * @param WP_Customize_Control $control WP_Customize_Control instance. */ do_action( "customize_render_control_{$this->id}", $this ); $this->render(); } /** * Renders the control wrapper and calls $this->render_content() for the internals. * * @since 3.4.0 */ protected function render() { $id = 'customize-control-' . str_replace( array( '[', ']' ), array( '-', '' ), $this->id ); $class = 'customize-control customize-control-' . $this->type; printf( '
  • ', esc_attr( $id ), esc_attr( $class ) ); $this->render_content(); echo '
  • '; } /** * Gets the data link attribute for a setting. * * @since 3.4.0 * @since 4.9.0 Return a `data-customize-setting-key-link` attribute if a setting is not registered for the supplied setting key. * * @param string $setting_key * @return string Data link parameter, a `data-customize-setting-link` attribute if the `$setting_key` refers * to a pre-registered setting, and a `data-customize-setting-key-link` attribute if the setting * is not yet registered. */ public function get_link( $setting_key = 'default' ) { if ( isset( $this->settings[ $setting_key ] ) && $this->settings[ $setting_key ] instanceof WP_Customize_Setting ) { return 'data-customize-setting-link="' . esc_attr( $this->settings[ $setting_key ]->id ) . '"'; } else { return 'data-customize-setting-key-link="' . esc_attr( $setting_key ) . '"'; } } /** * Renders the data link attribute for the control's input element. * * @since 3.4.0 * @uses WP_Customize_Control::get_link() * * @param string $setting_key Default 'default'. */ public function link( $setting_key = 'default' ) { echo $this->get_link( $setting_key ); } /** * Renders the custom attributes for the control's input element. * * @since 4.0.0 */ public function input_attrs() { foreach ( $this->input_attrs as $attr => $value ) { echo $attr . '="' . esc_attr( $value ) . '" '; } } /** * Renders the control's content. * * Allows the content to be overridden without having to rewrite the wrapper in `$this::render()`. * * Supports basic input types `text`, `checkbox`, `textarea`, `radio`, `select` and `dropdown-pages`. * Additional input types such as `email`, `url`, `number`, `hidden` and `date` are supported implicitly. * * Control content can alternately be rendered in JS. See WP_Customize_Control::print_template(). * * @since 3.4.0 */ protected function render_content() { $input_id = '_customize-input-' . $this->id; $description_id = '_customize-description-' . $this->id; $describedby_attr = ( ! empty( $this->description ) ) ? ' aria-describedby="' . esc_attr( $description_id ) . '" ' : ''; switch ( $this->type ) { case 'checkbox': ?> type="checkbox" value="value() ); ?>" link(); ?> value() ); ?> /> description ) ) : ?> description; ?> choices ) ) { return; } $name = '_customize-radio-' . $this->id; ?> label ) ) : ?> label ); ?> description ) ) : ?> description; ?> choices as $value => $label ) : ?> value="" name="" link(); ?> value(), $value ); ?> /> choices ) ) { return; } ?> label ) ) : ?> description ) ) : ?> description; ?> input_attrs ) ) { $this->input_attrs['rows'] = 5; } ?> label ) ) : ?> description ) ) : ?> description; ?> label ) ) : ?> description ) ) : ?> description; ?> id; $show_option_none = __( '— Select —' ); $option_none_value = '0'; $dropdown = wp_dropdown_pages( array( 'name' => $dropdown_name, 'echo' => 0, 'show_option_none' => $show_option_none, 'option_none_value' => $option_none_value, 'selected' => $this->value(), ) ); if ( empty( $dropdown ) ) { $dropdown = sprintf( ''; } // Hackily add in the data link parameter. $dropdown = str_replace( 'get_link() . ' id="' . esc_attr( $input_id ) . '" ' . $describedby_attr, $dropdown ); /* * Even more hackily add auto-draft page stubs. * @todo Eventually this should be removed in favor of the pages being injected into the underlying get_pages() call. * See . */ $nav_menus_created_posts_setting = $this->manager->get_setting( 'nav_menus_created_posts' ); if ( $nav_menus_created_posts_setting && current_user_can( 'publish_pages' ) ) { $auto_draft_page_options = ''; foreach ( $nav_menus_created_posts_setting->value() as $auto_draft_page_id ) { $post = get_post( $auto_draft_page_id ); if ( $post && 'page' === $post->post_type ) { $auto_draft_page_options .= sprintf( '', esc_attr( $post->ID ), esc_html( $post->post_title ) ); } } if ( $auto_draft_page_options ) { $dropdown = str_replace( '', $auto_draft_page_options . '', $dropdown ); } } echo $dropdown; ?> allow_addition && current_user_can( 'publish_pages' ) && current_user_can( 'edit_theme_options' ) ) : // Currently tied to menus functionality. ?>
    label ) ) : ?> description ) ) : ?> description; ?> input_attrs(); ?> input_attrs['value'] ) ) : ?> value="value() ); ?>" link(); ?> />