enum']; } if ( ( ! isset( $config['required'] ) || true !== $config['required'] ) && ! in_array( $property, $required, true ) ) { $param['optional'] = true; } if ( isset( $config['description'] ) ) { $param['description'] = $config['description']; } $synopsis[] = $param; } } if ( ! empty( $schema['additionalProperties'] ) ) { $synopsis[] = [ 'type' => 'generic', ]; } return $synopsis; } /** * Decode a string with URL-safe Base64. * * @param string $input A Base64 encoded string * * @return string A decoded string */ public static function url_safe_b64_decode( $input ) { $remainder = strlen( $input ) % 4; if ( $remainder ) { $padlen = 4 - $remainder; $input .= str_repeat( '=', $padlen ); } return base64_decode( strtr( $input, '-_', '+/' ) ); } /** * Encode a string with URL-safe Base64. * * @param string $input The string you want encoded * * @return string The base64 encode of what you passed in */ public static function url_safe_b64_encode( $input ) { return str_replace( '=', '', strtr( base64_encode( $input ), '+/', '-_' ) ); } /** * Compares the WordPress version with the given version. * * @param string $version The version to compare with. * @param string $operator The operator. * @param bool $allow_dev Whether to treat dev versions as stable. * * @return bool */ public static function wp_version_compare( $version, $operator, $allow_dev = true ) { global $wp_version; if ( $allow_dev ) { list( $wp_version ) = explode( '-', $wp_version ); } return version_compare( $wp_version, $version, $operator ); } /** * Checks if the WordPress version is at least the given version. * * @param string $version The version to check WP for. * @param bool $allow_dev Whether to treat dev versions as stable. * * @return bool */ public static function is_wp_version_at_least( $version, $allow_dev = true ) { return static::wp_version_compare( $version, '>=', $allow_dev ); } /** * Gets the WordPress login URL. * * @param string $action A particular login action to use. * @param string $redirect Where to redirect the user to after login. * @param string $scheme The scheme to use. Accepts `login_post` for form submissions. * * @return string */ public static function get_login_url( $action = '', $redirect = '', $scheme = 'login' ) { if ( 'login_post' === $scheme || ( $action && 'login' !== $action ) ) { $url = 'wp-login.php'; if ( $action ) { $url = add_query_arg( 'action', urlencode( $action ), $url ); } if ( $redirect ) { $url = add_query_arg( 'redirect_to', urlencode( $redirect ), $url ); } $url = site_url( $url, $scheme ); } else { $url = wp_login_url( $redirect ); if ( $action ) { $url = add_query_arg( 'action', urlencode( $action ), $url ); } } if ( function_exists( 'is_wpe' ) && is_wpe() ) { $url = add_query_arg( 'wpe-login', 'true', $url ); } return apply_filters( 'itsec_login_url', $url, $action, $redirect, $scheme ); } /** * Extends a service definition, ignoring if the service has been frozen. * * @param \iThemesSecurity\Strauss\Pimple\Container $c * @param string $id * @param callable $extend * * @return bool */ public static function extend_if_able( \iThemesSecurity\Strauss\Pimple\Container $c, string $id, callable $extend ): bool { try { $c->extend( $id, $extend ); return true; } catch ( \iThemesSecurity\Strauss\Pimple\Exception\FrozenServiceException $e ) { return false; } } /** * Resolve JSON Schema refs. * * @param array $schema * * @return array */ public static function resolve_schema_refs( array $schema ): array { if ( isset( $schema['definitions'] ) ) { array_walk( $schema, [ static::class, 'resolve_ref' ], $schema['definitions'] ); } return $schema; } /** * Resolves $ref entries at any point in the config. * * Currently, only a simplified form of JSON Pointers are supported where `/` is the only * allowed control character. * * Additionally, the `$ref` keyword must start with `#/definitions`. * * @param mixed $value The incoming value. * @param string $key The array key. * @param array $definitions The shared definitions. */ private static function resolve_ref( &$value, $key, $definitions ) { if ( ! is_array( $value ) ) { return; } if ( isset( $value['$ref'] ) ) { $ref = str_replace( '#/definitions/', '', $value['$ref'] ); $value = \ITSEC_Lib::array_get( $definitions, $ref, null, '/' ); return; } array_walk( $value, [ static::class, 'resolve_ref' ], $definitions ); } /** * Generates a v4 UUID using a CSPRNG. * * @return string */ public static function generate_uuid4(): string { return sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ), wp_rand( 0, 0x0fff ) | 0x4000, wp_rand( 0, 0x3fff ) | 0x8000, wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ), wp_rand( 0, 0xffff ) ); } /** * Clears the WordPress auth cookies. * * This function is safe to call before plugins have been loaded. * But the request MUST exist after calling it. * * @return void */ public static function clear_auth_cookie() { if ( ! function_exists( 'wp_clear_auth_cookie' ) ) { if ( is_multisite() ) { ms_cookie_constants(); } // Define constants after multisite is loaded. wp_cookie_constants(); require_once ABSPATH . 'wp-includes/pluggable.php'; } wp_clear_auth_cookie(); } public static function recursively_json_serialize( $value ) { if ( $value instanceof JsonSerializable ) { return $value->jsonSerialize(); } if ( is_array( $value ) ) { foreach ( $value as $k => $v ) { $value[ $k ] = self::recursively_json_serialize( $v ); } } return $value; } }