in. */ function rest_authorization_required_code() { return is_user_logged_in() ? 403 : 401; } /** * Validate a request argument based on details registered to the route. * * @since 4.7.0 * * @param mixed $value * @param WP_REST_Request $request * @param string $param * @return WP_Error|boolean */ function rest_validate_request_arg( $value, $request, $param ) { $attributes = $request->get_attributes(); if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { return true; } $args = $attributes['args'][ $param ]; return rest_validate_value_from_schema( $value, $args, $param ); } /** * Sanitize a request argument based on details registered to the route. * * @since 4.7.0 * * @param mixed $value * @param WP_REST_Request $request * @param string $param * @return mixed */ function rest_sanitize_request_arg( $value, $request, $param ) { $attributes = $request->get_attributes(); if ( ! isset( $attributes['args'][ $param ] ) || ! is_array( $attributes['args'][ $param ] ) ) { return $value; } $args = $attributes['args'][ $param ]; return rest_sanitize_value_from_schema( $value, $args ); } /** * Parse a request argument based on details registered to the route. * * Runs a validation check and sanitizes the value, primarily to be used via * the `sanitize_callback` arguments in the endpoint args registration. * * @since 4.7.0 * * @param mixed $value * @param WP_REST_Request $request * @param string $param * @return mixed */ function rest_parse_request_arg( $value, $request, $param ) { $is_valid = rest_validate_request_arg( $value, $request, $param ); if ( is_wp_error( $is_valid ) ) { return $is_valid; } $value = rest_sanitize_request_arg( $value, $request, $param ); return $value; } /** * Determines if an IP address is valid. * * Handles both IPv4 and IPv6 addresses. * * @since 4.7.0 * * @param string $ip IP address. * @return string|false The valid IP address, otherwise false. */ function rest_is_ip_address( $ip ) { $ipv4_pattern = '/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/'; if ( ! preg_match( $ipv4_pattern, $ip ) && ! Requests_IPv6::check_ipv6( $ip ) ) { return false; } return $ip; } /** * Changes a boolean-like value into the proper boolean value. * * @since 4.7.0 * * @param bool|string|int $value The value being evaluated. * @return boolean Returns the proper associated boolean value. */ function rest_sanitize_boolean( $value ) { // String values are translated to `true`; make sure 'false' is false. if ( is_string( $value ) ) { $value = strtolower( $value ); if ( in_array( $value, array( 'false', '0' ), true ) ) { $value = false; } } // Everything else will map nicely to boolean. return (boolean) $value; } /** * Determines if a given value is boolean-like. * * @since 4.7.0 * * @param bool|string $maybe_bool The value being evaluated. * @return boolean True if a boolean, otherwise false. */ function rest_is_boolean( $maybe_bool ) { if ( is_bool( $maybe_bool ) ) { return true; } if ( is_string( $maybe_bool ) ) { $maybe_bool = strtolower( $maybe_bool ); $valid_boolean_values = array( 'false', 'true', '0', '1', ); return in_array( $maybe_bool, $valid_boolean_values, true ); } if ( is_int( $maybe_bool ) ) { return in_array( $maybe_bool, array( 0, 1 ), true ); } return false; } /** * Retrieves the avatar urls in various sizes based on a given email address. * * @since 4.7.0 * * @see get_avatar_url() * * @param string $email Email address. * @return array $urls Gravatar url for each size. */ function rest_get_avatar_urls( $email ) { $avatar_sizes = rest_get_avatar_sizes(); $urls = array(); foreach ( $avatar_sizes as $size ) { $urls[ $size ] = get_avatar_url( $email, array( 'size' => $size ) ); } return $urls; } /** * Retrieves the pixel sizes for avatars. * * @since 4.7.0 * * @return array List of pixel sizes for avatars. Default `[ 24, 48, 96 ]`. */ function rest_get_avatar_sizes() { /** * Filters the REST avatar sizes. * * Use this filter to adjust the array of sizes returned by the * `rest_get_avatar_sizes` function. * * @since 4.4.0 * * @param array $sizes An array of int values that are the pixel sizes for avatars. * Default `[ 24, 48, 96 ]`. */ return apply_filters( 'rest_avatar_sizes', array( 24, 48, 96 ) ); } /** * Validate a value based on a schema. * * @since 4.7.0 * * @param mixed $value The value to validate. * @param array $args Schema array to use for validation. * @param string $param The parameter name, used in error messages. * @return true|WP_Error */ function rest_validate_value_from_schema( $value, $args, $param = '' ) { if ( 'array' === $args['type'] ) { if ( ! is_array( $value ) ) { $value = preg_split( '/[\s,]+/', $value ); } if ( ! wp_is_numeric_array( $value ) ) { /* translators: 1: parameter, 2: type name */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'array' ) ); } foreach ( $value as $index => $v ) { $is_valid = rest_validate_value_from_schema( $v, $args['items'], $param . '[' . $index . ']' ); if ( is_wp_error( $is_valid ) ) { return $is_valid; } } } if ( ! empty( $args['enum'] ) ) { if ( ! in_array( $value, $args['enum'], true ) ) { /* translators: 1: parameter, 2: list of valid values */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not one of %2$s.' ), $param, implode( ', ', $args['enum'] ) ) ); } } if ( in_array( $args['type'], array( 'integer', 'number' ) ) && ! is_numeric( $value ) ) { /* translators: 1: parameter, 2: type name */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, $args['type'] ) ); } if ( 'integer' === $args['type'] && round( floatval( $value ) ) !== floatval( $value ) ) { /* translators: 1: parameter, 2: type name */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'integer' ) ); } if ( 'boolean' === $args['type'] && ! rest_is_boolean( $value ) ) { /* translators: 1: parameter, 2: type name */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $value, 'boolean' ) ); } if ( 'string' === $args['type'] && ! is_string( $value ) ) { /* translators: 1: parameter, 2: type name */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s is not of type %2$s.' ), $param, 'string' ) ); } if ( isset( $args['format'] ) ) { switch ( $args['format'] ) { case 'date-time' : if ( ! rest_parse_date( $value ) ) { return new WP_Error( 'rest_invalid_date', __( 'Invalid date.' ) ); } break; case 'email' : if ( ! is_email( $value ) ) { return new WP_Error( 'rest_invalid_email', __( 'Invalid email address.' ) ); } break; case 'ip' : if ( ! rest_is_ip_address( $value ) ) { /* translators: %s: IP address */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%s is not a valid IP address.' ), $value ) ); } break; } } if ( in_array( $args['type'], array( 'number', 'integer' ), true ) && ( isset( $args['minimum'] ) || isset( $args['maximum'] ) ) ) { if ( isset( $args['minimum'] ) && ! isset( $args['maximum'] ) ) { if ( ! empty( $args['exclusiveMinimum'] ) && $value <= $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than %2$d' ), $param, $args['minimum'] ) ); } elseif ( empty( $args['exclusiveMinimum'] ) && $value < $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be greater than or equal to %2$d' ), $param, $args['minimum'] ) ); } } elseif ( isset( $args['maximum'] ) && ! isset( $args['minimum'] ) ) { if ( ! empty( $args['exclusiveMaximum'] ) && $value >= $args['maximum'] ) { /* translators: 1: parameter, 2: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than %2$d' ), $param, $args['maximum'] ) ); } elseif ( empty( $args['exclusiveMaximum'] ) && $value > $args['maximum'] ) { /* translators: 1: parameter, 2: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be less than or equal to %2$d' ), $param, $args['maximum'] ) ); } } elseif ( isset( $args['maximum'] ) && isset( $args['minimum'] ) ) { if ( ! empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { if ( $value >= $args['maximum'] || $value <= $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number, 3: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); } } elseif ( empty( $args['exclusiveMinimum'] ) && ! empty( $args['exclusiveMaximum'] ) ) { if ( $value >= $args['maximum'] || $value < $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number, 3: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (exclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); } } elseif ( ! empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { if ( $value > $args['maximum'] || $value <= $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number, 3: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (exclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); } } elseif ( empty( $args['exclusiveMinimum'] ) && empty( $args['exclusiveMaximum'] ) ) { if ( $value > $args['maximum'] || $value < $args['minimum'] ) { /* translators: 1: parameter, 2: minimum number, 3: maximum number */ return new WP_Error( 'rest_invalid_param', sprintf( __( '%1$s must be between %2$d (inclusive) and %3$d (inclusive)' ), $param, $args['minimum'], $args['maximum'] ) ); } } } } return true; } /** * Sanitize a value based on a schema. * * @since 4.7.0 * * @param mixed $value The value to sanitize. * @param array $args Schema array to use for sanitization. * @return true|WP_Error */ function rest_sanitize_value_from_schema( $value, $args ) { if ( 'array' === $args['type'] ) { if ( empty( $args['items'] ) ) { return (array) $value; } if ( ! is_array( $value ) ) { $value = preg_split( '/[\s,]+/', $value ); } foreach ( $value as $index => $v ) { $value[ $index ] = rest_sanitize_value_from_schema( $v, $args['items'] ); } // Normalize to numeric array so nothing unexpected // is in the keys. $value = array_values( $value ); return $value; } if ( 'integer' === $args['type'] ) { return (int) $value; } if ( 'number' === $args['type'] ) { return (float) $value; } if ( 'boolean' === $args['type'] ) { return rest_sanitize_boolean( $value ); } if ( isset( $args['format'] ) ) { switch ( $args['format'] ) { case 'date-time' : return sanitize_text_field( $value ); case 'email' : /* * sanitize_email() validates, which would be unexpected. */ return sanitize_text_field( $value ); case 'uri' : return esc_url_raw( $value ); case 'ip' : return sanitize_text_field( $value ); } } if ( 'string' === $args['type'] ) { return strval( $value ); } return $value; } Complete Safety Analysis