array( 'class' => true, 'style' => true, // Most data for the popup is saved in the data attributes. 'data-*' => true, ), 'div' => array( 'class' => true, 'style' => true, // Most data for the popup is saved in the data attributes. 'data-*' => true, ), ); return array_merge( $allowedtags, $kses_defaults, $kses_popup ); } return $allowedtags; } /** * Returns allowed HTML tags and attributes for Svg. * * @param string|array $allowedtags - Allow Tags for current context. * @param string|array $context - tags context. * * @return array */ public function wp_kses_vp_svg( $allowedtags, $context ) { if ( 'vp_svg' === $context ) { $kses_svg_attrs = array( 'x' => true, 'y' => true, 'd' => true, 'r' => true, 'width' => true, 'height' => true, 'rx' => true, 'cx' => true, 'cy' => true, 'stroke' => true, 'stroke-width' => true, 'fill' => true, 'transform' => true, 'stroke-linecap' => true, 'stroke-linejoin' => true, ); $kses_svg = array( 'svg' => array( 'class' => true, 'aria-hidden' => true, 'aria-labelledby' => true, 'role' => true, 'xmlns' => true, 'width' => true, 'height' => true, 'viewbox' => true, ), 'g' => $kses_svg_attrs, 'path' => $kses_svg_attrs, 'rect' => $kses_svg_attrs, 'circle' => $kses_svg_attrs, 'title' => array( 'title' => true, ), ); return $kses_svg; } return $allowedtags; } /** * Returns allowed HTML tags and attributes for Svg. * * @param string|array $allowedtags - Allow Tags for current context. * @param string|array $context - tags context. * * @return array */ public function wp_kses_vp_image( $allowedtags, $context ) { if ( 'vp_image' === $context ) { $kses_image = array( 'noscript' => true, 'img' => array( 'alt' => true, 'align' => true, 'border' => true, 'class' => true, 'height' => true, 'hspace' => true, 'loading' => true, 'longdesc' => true, 'vspace' => true, 'src' => true, 'srcset' => true, 'sizes' => true, 'usemap' => true, 'width' => true, // Lazy loading data is saved in the data attributes. 'data-*' => true, ), 'figure' => array( 'align' => true, ), 'figcaption' => array( 'align' => true, ), ); return $kses_image; } return $allowedtags; } /** * Sanitize hidden attribute. * * @param string|bool $attribute - Unclear Hidden Attribute. * @return string|bool */ public static function sanitize_hidden( $attribute ) { $value = false; if ( is_bool( $attribute ) ) { $value = (bool) $attribute; } elseif ( is_string( $attribute ) ) { $value = strtolower( $attribute ); if ( in_array( $value, array( 'false', '0' ), true ) ) { $value = false; } if ( in_array( $value, array( 'true', '1' ), true ) ) { $value = true; } $value = is_bool( $value ) ? (bool) $value : sanitize_text_field( wp_unslash( $attribute ) ); } return $value; } /** * Sanitize Boolean. * * @param string|bool $attribute - Unclear Boolean Attribute. * @return bool */ public static function sanitize_boolean( $attribute ) { $value = false; if ( is_bool( $attribute ) ) { $value = (bool) $attribute; } elseif ( is_string( $attribute ) ) { $value = strtolower( $attribute ); if ( in_array( $value, array( 'false', '0' ), true ) ) { $value = false; } if ( in_array( $value, array( 'true', '1' ), true ) ) { $value = true; } $value = (bool) wp_unslash( $value ); } return $value; } /** * Sanitize selector attribute. * * @param int|float|string $attribute - Unclear Selector Attribute. * @return int|float|string */ public static function sanitize_selector( $attribute ) { if ( is_numeric( $attribute ) ) { if ( false === strpos( $attribute, '.' ) ) { $attribute = intval( $attribute ); } else { $attribute = (float) $attribute; } } else { $attribute = sanitize_text_field( wp_unslash( $attribute ) ); } return $attribute; } /** * Sanitize number attribute. * * @param string|int|float $attribute - Unclear Number Attribute. * @return int|float */ public static function sanitize_number( $attribute ) { $attribute = preg_replace( '/[^0-9.-]/', '', wp_unslash( $attribute ) ); // We should keep an empty string, because we allow resetting certain attributes. if ( '' === $attribute ) { $attribute = ''; } elseif ( false === strpos( $attribute, '.' ) ) { $attribute = intval( $attribute ); } else { $attribute = (float) $attribute; } return $attribute; } /** * Sanitize Element Selector. * * @param array $attribute - Unclear Element Selector Attribute. * @return array */ public static function sanitize_elements_selector( $attribute ) { $key = 'layout_elements'; if ( ! empty( $attribute ) && is_array( $attribute ) ) { $controls = Visual_Portfolio_Controls::get_registered_array(); $hight_level_allowed_locations = array_keys( $controls[ $key ]['locations'] ); foreach ( $attribute as $locations_key => $locations ) { if ( false !== array_search( $locations_key, $hight_level_allowed_locations, true ) && ! empty( $locations ) && is_array( $locations ) ) { $low_level_allowed_locations = array( 'elements' ); if ( isset( $controls[ $key ]['locations'][ $locations_key ]['align'] ) && ! empty( $controls[ $key ]['locations'][ $locations_key ]['align'] ) ) { $low_level_allowed_locations = array_merge( $low_level_allowed_locations, array( 'align' ) ); $allowed_align_protocol = $controls[ $key ]['locations'][ $locations_key ]['align']; } foreach ( $locations as $location_key => $location ) { if ( false !== array_search( $location_key, $low_level_allowed_locations, true ) ) { if ( 'align' === $location_key && isset( $allowed_align_protocol ) && false !== array_search( $location, $allowed_align_protocol, true ) ) { $attribute[ $locations_key ][ $location_key ] = sanitize_text_field( wp_unslash( $location ) ); } elseif ( 'elements' === $location_key && is_array( $location ) ) { foreach ( $location as $item_key => $item ) { if ( false !== array_search( $locations_key, $controls[ $key ]['options'][ $item ]['allowed_locations'], true ) && isset( $controls[ $key ]['options'][ $item ]['allowed_locations'] ) ) { $attribute[ $locations_key ][ $location_key ][ $item_key ] = sanitize_text_field( wp_unslash( $item ) ); } else { unset( $attribute[ $locations_key ][ $location_key ][ $item_key ] ); } } } else { unset( $attribute[ $locations_key ][ $location_key ] ); } } else { unset( $attribute[ $locations_key ][ $location_key ] ); } } } else { unset( $attribute[ $locations_key ] ); } } } else { $attribute = array(); } return $attribute; } /** * Sanitize Gallery. * * @param array $attribute - Unclear Gallery Attribute. * @return array */ public static function sanitize_gallery( $attribute ) { if ( isset( $attribute ) && ! empty( $attribute ) ) { foreach ( $attribute as $key => $gallery_item ) { if ( isset( $gallery_item ) && ! empty( $gallery_item ) ) { foreach ( $gallery_item as $attribute_key => $media_attribute ) { switch ( $attribute_key ) { case 'imgUrl': case 'imgThumbnailUrl': case 'video_url': case 'author_url': case 'post_url': case 'url': $attribute[ $key ][ $attribute_key ] = esc_url_raw( wp_unslash( $media_attribute ) ); break; case 'hover_image_focal_point': case 'focalPoint': if ( isset( $media_attribute ) && ! empty( $media_attribute ) ) { foreach ( $media_attribute as $focal_key => $focal_point ) { $attribute[ $key ][ $attribute_key ][ $focal_key ] = self::sanitize_number( $focal_point ); } } else { $attribute[ $key ][ $attribute_key ] = null; } break; case 'custom_popup_image': case 'hover_image': $attribute[ $key ][ $attribute_key ] = self::sanitize_number( $media_attribute ); break; case 'categories': if ( isset( $media_attribute ) && ! empty( $media_attribute ) ) { foreach ( $media_attribute as $category_key => $category ) { $attribute[ $key ][ $attribute_key ][ $category_key ] = sanitize_text_field( wp_unslash( $category ) ); } } else { $attribute[ $key ][ $attribute_key ] = null; } break; case 'title': case 'description': $attribute[ $key ][ $attribute_key ] = wp_kses_post( wp_unslash( $media_attribute ) ); break; case 'id': case 'author': case 'format': case 'deep_link_pid': default: $attribute[ $key ][ $attribute_key ] = sanitize_text_field( wp_unslash( $media_attribute ) ); break; } } } } } else { $attribute = array(); } return $attribute; } /** * Sanitize Attributes. * * @param array $attributes - Attributes. * @return array */ public static function sanitize_attributes( $attributes = array() ) { if ( ! empty( $attributes ) ) { $controls = Visual_Portfolio_Controls::get_registered_array(); foreach ( $attributes as $key => $attribute ) { if ( 0 === strpos( $key, 'vp_' ) ) { $key = preg_replace( '/^vp_/', '', $key ); $mode = 'preview'; $attributes[ $key ] = $attribute; unset( $attributes[ 'vp_' . $key ] ); } $sanitize_callback = $controls[ $key ]['sanitize_callback'] ?? false; if ( $sanitize_callback ) { $finding_class = is_string( $sanitize_callback ) && strripos( $sanitize_callback, '::' ); if ( false === $finding_class && is_callable( array( __CLASS__, $sanitize_callback ) ) ) { $attributes[ $key ] = call_user_func( array( __CLASS__, $sanitize_callback ), $attribute ); } else { $attributes[ $key ] = call_user_func( $sanitize_callback, $attribute ); } } else { $type = $controls[ $key ]['type'] ?? false; switch ( $type ) { case 'hidden': case 'checkbox': $attributes[ $key ] = self::sanitize_hidden( $attribute ); break; case 'icons_selector': case 'text': case 'radio': case 'align': case 'buttons': $attributes[ $key ] = sanitize_text_field( wp_unslash( $attribute ) ); break; case 'textarea': $attributes[ $key ] = sanitize_textarea_field( wp_unslash( $attribute ) ); break; case 'aspect_ratio': $attributes[ $key ] = preg_replace( '/[^0-9:]/', '', wp_unslash( $attribute ) ); break; case 'number': case 'range': $attributes[ $key ] = self::sanitize_number( $attribute ); break; case 'tiles_selector': $attributes[ $key ] = preg_replace( '/[^0-9.,|]/', '', wp_unslash( $attribute ) ); break; case 'select': $multiple = isset( $controls[ $key ]['multiple'] ) && ! empty( $controls[ $key ]['multiple'] ) ? $controls[ $key ]['multiple'] : false; if ( $multiple ) { $attributes[ $key ] = $attributes[ $key ] ?? $controls[ $key ]['default'] ?? array(); if ( is_array( $attributes[ $key ] ) && ! empty( $attributes[ $key ] ) ) { foreach ( $attributes[ $key ] as $attribute_key => $value ) { $attributes[ $key ][ $attribute_key ] = self::sanitize_selector( $value ); } } } else { $attributes[ $key ] = self::sanitize_selector( $attributes[ $key ] ); } break; case 'elements_selector': $attributes[ $key ] = self::sanitize_elements_selector( $attribute ); break; case 'code_editor': // Clear CSS. Maybe there will be an SVG validation error. $attributes[ $key ] = preg_replace( '# $value ) { $attributes[ $key ][ $attribute_key ] = sanitize_text_field( wp_unslash( $value ) ); } } else { $attributes[ $key ] = array(); } break; case 'gallery': $attributes[ $key ] = self::sanitize_gallery( $attribute ); break; case false: if ( 'block_id' === $key ) { $attributes[ $key ] = preg_replace( '/[^a-zA-Z0-9_-]/', '', wp_unslash( $attribute ) ); } else { $attributes[ $key ] = sanitize_text_field( wp_unslash( $attribute ) ); } break; default: $attributes[ $key ] = sanitize_text_field( wp_unslash( $attribute ) ); break; } } } if ( isset( $mode ) && 'preview' === $mode ) { foreach ( $attributes as $key => $attribute ) { $attributes[ 'vp_' . $key ] = $attribute; unset( $attributes[ $key ] ); } } } return $attributes; } } new Visual_Portfolio_Security();