[ 'href' => [], 'title' => [], 'target' => [], 'rel' => [], ], 'br' => [], 'em' => [], 'strong' => [], 'del' => [], 'p' => [ 'style' => [], ], 'blockquote' => [], 'ul' => [], 'ol' => [], 'li' => [], 'span' => [ 'style' => [], ], ]; return wp_kses( $error, $allow ); } /** * Sanitize a string, that can be a multiline. * * @uses wpforms_sanitize_text_deeply() * * @since 1.4.1 * * @param string $string String to deeply sanitize. * * @return string Sanitized string, or empty string if not a string provided. */ function wpforms_sanitize_textarea_field( $string ) { return wpforms_sanitize_text_deeply( $string, true ); } /** * Deeply sanitize the string, preserve newlines if needed. * Prevent maliciously prepared strings from containing HTML tags. * * @since 1.6.0 * * @param string $string String to deeply sanitize. * @param bool $keep_newlines Whether to keep newlines. Default: false. * * @return string Sanitized string, or empty string if not a string provided. */ function wpforms_sanitize_text_deeply( $string, $keep_newlines = false ) { if ( is_object( $string ) || is_array( $string ) ) { return ''; } $string = (string) $string; $keep_newlines = (bool) $keep_newlines; $new_value = _sanitize_text_fields( $string, $keep_newlines ); if ( strlen( $new_value ) !== strlen( $string ) ) { $new_value = wpforms_sanitize_text_deeply( $new_value, $keep_newlines ); } return $new_value; } /** * Sanitize an HTML string with a set of allowed HTML tags. * * @since 1.7.0 * * @param string $value String to sanitize. * * @return string Sanitized string. */ function wpforms_sanitize_richtext_field( $value ) { $count = 1; $value = convert_invalid_entities( $value ); // Remove 'script' and 'style' tags recursively. while ( $count ) { $value = preg_replace( '@<(script|style)[^>]*?>.*?@si', '', $value, - 1, $count ); } // Make sure we have allowed tags only. $value = wp_kses( $value, wpforms_get_allowed_html_tags_for_richtext_field() ); // Make sure that all tags are balanced. return force_balance_tags( $value ); } /** * Escaping for Rich Text field values. * * @since 1.7.0 * * @param string $value Text to escape. * * @return string Escaped text. */ function wpforms_esc_richtext_field( $value ) { return wpautop( wpforms_sanitize_richtext_field( $value ) ); } /** * Retrieve allowed HTML tags for Rich Text field. * * @since 1.7.0 * * @return array Array of allowed tags. */ function wpforms_get_allowed_html_tags_for_richtext_field() { $allowed_tags = array_fill_keys( [ 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'a', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'hr', 'br', 'code', 'pre', 'strong', 'b', 'em', 'i', 'blockquote', 'cite', 'q', 'del', 'span', 'small', 'table', 'thead', 'tbody', 'th', 'tr', 'td', 'abbr', 'address', 'sub', 'sup', 'ins', 'figure', 'figcaption', 'div', ], array_fill_keys( [ 'align', 'class', 'id', 'style', 'src', 'rel', 'alt', 'href', 'target', 'width', 'height', 'title', 'cite', 'start', 'reversed', 'datetime' ], [] ) ); /** * Allowed HTML tags for Rich Text field. * * @since 1.7.0 * * @param array $allowed_tags Allowed HTML tags. */ $tags = (array) apply_filters( 'wpforms_get_allowed_html_tags_for_richtext_field', $allowed_tags ); // Force unset iframes, script and style no matter when we get back // from apply_filters, as they are a huge security risk. unset( $tags['iframe'], $tags['script'], $tags['style'] ); return $tags; } /** * Sanitize an array, that consists of values as strings. * After that - merge all array values into multiline string. * * @since 1.4.1 * * @param array $array Data to sanitize. * * @return mixed If not an array is passed (or empty var) - return unmodified var. Otherwise - a merged array into multiline string. */ function wpforms_sanitize_array_combine( $array ) { if ( empty( $array ) || ! is_array( $array ) ) { return $array; } return implode( "\n", array_map( 'sanitize_text_field', $array ) ); } /** * Format, sanitize, and return/echo HTML element ID, classes, attributes, * and data attributes. * * @since 1.3.7 * * @param string $id HTML id attribute value. * @param array $class A list of classnames for the class attribute. * @param array $datas Data attributes. * @param array $atts Any additional HTML attributes and their values. * @param bool $echo Whether to echo the output or just return it. Defaults to return. * * @return string|void */ function wpforms_html_attributes( $id = '', $class = [], $datas = [], $atts = [], $echo = false ) { $id = trim( $id ); $parts = []; if ( ! empty( $id ) ) { $id = sanitize_html_class( $id ); if ( ! empty( $id ) ) { $parts[] = 'id="' . $id . '"'; } } if ( ! empty( $class ) ) { $class = wpforms_sanitize_classes( $class, true ); if ( ! empty( $class ) ) { $parts[] = 'class="' . $class . '"'; } } if ( ! empty( $datas ) ) { foreach ( $datas as $data => $val ) { $parts[] = 'data-' . sanitize_html_class( $data ) . '="' . esc_attr( $val ) . '"'; } } if ( ! empty( $atts ) ) { foreach ( $atts as $att => $val ) { if ( '0' === (string) $val || ! empty( $val ) ) { if ( $att[0] === '[' ) { // Handle special case for bound attributes in AMP. $escaped_att = '[' . sanitize_html_class( trim( $att, '[]' ) ) . ']'; } else { $escaped_att = sanitize_html_class( $att ); } $parts[] = $escaped_att . '="' . esc_attr( $val ) . '"'; } } } $output = implode( ' ', $parts ); if ( $echo ) { echo trim( $output ); // phpcs:ignore } else { return trim( $output ); } } /** * Sanitize string of CSS classes. * * @since 1.2.1 * * @param array|string $classes CSS classes. * @param bool $convert True will convert strings to array and vice versa. * * @return string|array */ function wpforms_sanitize_classes( $classes, $convert = false ) { $array = is_array( $classes ); $css = []; if ( ! empty( $classes ) ) { if ( ! $array ) { $classes = explode( ' ', trim( $classes ) ); } foreach ( array_unique( $classes ) as $class ) { if ( ! empty( $class ) ) { $css[] = sanitize_html_class( $class ); } } } if ( $array ) { return $convert ? implode( ' ', $css ) : $css; } return $convert ? $css : implode( ' ', $css ); } /** * Include a template - alias to \WPForms\Helpers\Template::get_html. * Use 'require' if $args are passed or 'load_template' if not. * * @since 1.5.6 * * @param string $template_name Template name. * @param array $args Arguments. * @param bool $extract Extract arguments. * * @throws RuntimeException If extract() tries to modify the scope. * * @return string Compiled HTML. */ function wpforms_render( $template_name, $args = [], $extract = false ) { return Templates::get_html( $template_name, $args, $extract ); } /** * Alias for default readonly function. * * @since 1.6.9 * * @param mixed $readonly One of the values to compare. * @param mixed $current The other value to compare if not just true. * @param bool $echo Whether to echo or just return the string. * * @return string HTML attribute or empty string. */ function wpforms_readonly( $readonly, $current = true, $echo = true ) { if ( function_exists( 'wp_readonly' ) ) { return wp_readonly( $readonly, $current, $echo ); } return __checked_selected_helper( $readonly, $current, $echo, 'readonly' ); } /** * Get the required label text, with a filter. * * @since 1.4.4 * * @return string */ function wpforms_get_required_label() { return apply_filters( 'wpforms_required_label', esc_html__( 'This field is required.', 'wpforms-lite' ) ); } /** * Get the required field label HTML, with a filter. * * @since 1.4.8 * * @return string */ function wpforms_get_field_required_label() { $label_html = apply_filters_deprecated( 'wpforms_field_required_label', [ ' *' ], '1.4.8 of the WPForms plugin', 'wpforms_get_field_required_label' ); return apply_filters( 'wpforms_get_field_required_label', $label_html ); } /** * Escape unselected choices for radio/checkbox fields. * * @since 1.8.3 * * @param string $formatted_field HTML field. * * @return string */ function wpforms_esc_unselected_choices( $formatted_field ) { $allowed_html = wp_kses_allowed_html( 'post' ); $allowed_html['input'] = [ 'type' => [], 'disabled' => [], 'checked' => [], ]; $allowed_html['label'] = []; return wp_kses( $formatted_field, $allowed_html ); }